最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中Object和內部類舉例詳解

 更新時間:2025年05月16日 11:25:47   作者:遇見你的雩風  
這篇文章主要介紹了Java中Object和內部類的相關資料,Object類是Java中所有類的父類,提供了toString、hashCode和equals等方法,內部類分為實例內部類、靜態(tài)內部類、匿名內部類和局部內部類,需要的朋友可以參考下

前言:

上期內容為大家?guī)砹顺橄箢惻c接口的知識點的學習,這期內容我將為大家?guī)砹薕bject類與內部類的兩種類的學習,這其內容是對于類與對象的補充。

一、Object類

1.object類初識

Object類是Java中一個默認提供的類,Java里面內置了object類,其余所有的類都是具有繼承關系的,默認繼承Object父類,那么也就是所有的對象都是可以使用object的引用來接收。

所以也可以發(fā)生了向上轉型。

class Person1{}
class Student{}
class Test {
    public static void main(String[] args) {
        function(new Person1());
        function(new Student());
    }
    public static void function(Object obj) {
        System.out.println(obj);
    }
}

這個時候我們可以看到打印的是對象所在位置的類型名和哈希值。

通過API文檔,我們可以看到object類中有許多方法,這些方法我們都要全部掌握!

但是我們已經(jīng)學習了clone方法了,這節(jié)我們要掌握三種方法,分別是:toString,hashCode,equals方法

hashCode我們后期在哈希表會再次進行詳細的講解。

2.Object的方法

2.(1).獲取對象的信息–toString方法

class Person{
    public String name;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }  
}
public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("張三",10);
        System.out.println(person1);
        Person person2 = new Person("張三",10);
        System.out.println(person2);
}   

這個時候我們看到打印的是對象所在位置的類型的名和哈希值

我們看一下Object類中toString方法的源碼:

獲取的是對象所在位置的類型的名和哈希值。

如果我們想要打印對象的成員信息,這個時候我們可以重寫這個toString方法,去獲取對象成員變量的信息。

class Person{
    public String name;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("張三",10);
        System.out.println(person1);
        Person person2 = new Person("張三",10);
        System.out.println(person2);
}    

既然重寫toString方法,那么就會發(fā)生了多態(tài)。

2.(2).對象比較equals方法

在Java中,我們要比較兩者數(shù)據(jù)之間的是否一樣用等于號來進行,比如我們用==來進行比較,如果兩者不一樣,則返回假,一樣就返回真。

public static void main(String[] args) {
        int a = 10;
        int b = 10;
        System.out.println(a == b);
}
//這個時候我們打印會的是true

那么我們比較兩個自定義類型呢?

 public static void main(String[] args) {
        Person person1 = new Person("張三",10);
        System.out.println(person1);
        Person person2 = new Person("張三",10);
        System.out.println(person2);
        System.out.println("=========");
        System.out.println(person1 == person2);
}

這里表明了兩個person不是同一個,為什么會出現(xiàn)這種情況呢?那么我們此時來觀察一下他們所處的地址

我們看到了這兩地址也就是哈希值是完全不同的,所以我們可以明白"=="

是比較自定義類型的地址是否是完全相同的。

有一個方法叫做equals,也是比較兩個對象是否相同,下面我們可以看看這個方法的源碼:

我們會發(fā)現(xiàn)它返回的是也是地址,比較判斷對象是否指向了一個同一個地址。

所以直接調用還是會為false但是我們不想讓它比較的是地址,就像上述代碼一般,兩個張三的實例化,就應該是同一個對象,所以這個時候就要涉及到重寫equals方法了。

class Person{
    public String name;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Person person1 = new Person("張三",10);
        System.out.println(person1);
        Person person2 = new Person("張三",10);
        System.out.println(person2);
        System.out.println("=========");
        System.out.println(person1 == person2);//比較兩者實例化后是不是一個person
        //結果是false
        //通過直接打印了它們的地址,發(fā)現(xiàn)兩者的地址不同
        //所以  時候比較的就是變量中的值
        System.out.println(person1.equals(person2));
	}
}

這個時候我們重寫equals方法,這個時候的結果就是:true

上述代碼這個重寫equals方法是IDEA為我們進行重寫的,我們可以自己手動重寫一個equals方法

比如:

 @Override
    public boolean equals(Object obj) {
        if (obj == null) {//如果是被比較的對象是空類型
            return false ;
        }
        if(this == obj) {//兩者指向了一個對象的空間,那么獲得的地址是一個,所以兩者是一個
            return true ;
        }
        // 不是Person類對象
        if (!(obj instanceof Person)) {//判斷person
            return false ;
        }
        Person person = (Person) obj ; // 向下轉型,比較屬性值,兩者的屬性是自己定義的,不是object類
        return this.name.equals(person.name) && this.age==person.age ;
    }

兩者的邏輯是一樣的,都可以實現(xiàn)equals方法重寫。

結論:所以通過equals方法的比較,我們要明白:如果是以后自定義的類型,那么一定要記住重寫equals方法
并且在比較對象中內容是否相同的時候,一定要重寫equals方法。

2.(3).hashCode方法

哈希值:hashcode這個方法會幫我們算出一個地址以16進制輸出我們看到對象那個的打印的時候,我們會發(fā)現(xiàn)打印了哈希值,也就是這個方法

hashCode方法,那么我們可以進行查看一下hashCode的源碼:

native的方法代表著我們是本地方法,用C/C++來進行寫的方法,所以我們也看不到的這個方法中的具體實現(xiàn)。

比如我們這個時候直接打印一下它們的哈希值:

System.out.println(person1.hashCode());
System.out.println(person2.hashCode());

我們可以發(fā)現(xiàn)兩者的哈希值是不同的,但是也代表兩者的地址不同,因為我們認為兩個名字相同,年齡相同的對象,將存儲在同一個位置,所以這個時候我們就需要重寫hashCode()方法了

我們在Person類中重寫了hashCode方法:

	@Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

這個時候再來比較person1和person2是否相同:

我們可以看到結果是兩者的哈希值是一樣的。

如果我們沒有重寫了hashCode方法,那么就是直接打印的是兩者的哈希值。

如果我們判斷名字和姓名是一樣,那么就不需要重復在開辟空間了,所以我們這個時候可以重寫hashcode

所以我們重寫的hashcode會發(fā)現(xiàn)某些對象出現(xiàn)在堆中同一個位置

后期講到哈希表的時候便會知道(現(xiàn)實邏輯中的)如果兩個一樣的對象想放在同一個位置,
此時我就可以利用重寫hashcode這個方法來實現(xiàn)
結論:
1、hashcode方法用來確定對象在內存中存儲的位置是否相同
2、事實上hashCode() 在散列表中才有用,在其它情況下沒用。在散列表中hashCode() 的作用是獲取對象的
散列碼,進而確定該對象在散列表中的位置。

二、內部類

1.內部類初識:

內部類:

在 Java 中,可以將一個類定義在另一個類或者一個方法的內部,前者稱為內部類,后者稱為外部類。內部類也是封裝的一種體現(xiàn)。
關于類,我們深知是一個類只有一個對應的字節(jié)碼文件,但是如果我們遇到這種內部類,會發(fā)現(xiàn)一個類中還有一定的類,我們先寫一個內部類,觀察一下:

class OutClass{
    class InnerClass{

    }
}

通過IDEA打開了本地文件的字節(jié)碼的文件:

我們可以看到它有OutClass和OutClass$InnerClass兩個字節(jié)碼文件

所以我們就可以知道內部類是外部類$內部類,當然還有一種是外部類$數(shù)字,我們會在后面講解。

2.內部類的分類:

有三種內部類:靜態(tài)、實例、匿名、局部 總共三種內部類;

使用頻率:實例>靜態(tài)>匿名>局部

2.(1).實例內部類

實例內部類就是在普通的類中去定義一個類,比如我們定義一個實例內部類:

class OutClass1{
    public int data1 = 1;
    public int data2 = 2;
    public static int data3 = 3;
    class InnerClass{
        public int data1 = 11111;
        public int data4 = 4;
        private int data5 = 5;
        public static int data6 = 6;
        public void test(){
            System.out.println(data1);
            System.out.println(data5);
            System.out.println("內部類的test方法");
        }
    }

    public void test(){
        System.out.println("外部類的test方法");
    }
}

我們定義一個實例內部類,這個時候我們來執(zhí)行這個實例內部類

public class Test2 {
    public static void main(String[] args) {
        OutClass1 outClass1 = new OutClass1(); 
        System.out.println(outClass1.data1);
        System.out.println("================");
        InnerClass innerClass = new InnerClass();
       
    }
}     

這時候就會顯示報錯:

所以實例內部類不能同正常的類去進行實例化,我們應該注意,用外部類訪問內部類

所以我們用外部類名去訪問內部類:

OutClass1 outClass1 = new OutClass1(); 
OutClass1.InnerClass innerClass = outClass1.new InnerClass();//我們用對象名去調用內部類名
innerClass.test();

//上述這種寫法是把outClass的對象名給其去調用
//我們也可以直接把對象引用:
OutClass1.InnerClass innerClass2 = new OutClass1().new InnerClass();
innerClass2.test();

當內部類數(shù)據(jù)成員和外部類數(shù)據(jù)成員是同名的時候,會怎么樣?,讓我們來進行看一下:

這次執(zhí)行成功了,但是我們會發(fā)現(xiàn)了外部類與內部類均有data1,但是我們發(fā)現(xiàn)打印的是內部類中的data1,

這個時候就是前面所講的就近原則,Java的編譯器進行檢查的時候,發(fā)現(xiàn)內部類的data1與其位置最近,那么優(yōu)先訪問它

那么我們要訪問外部的data1呢?我們可以加上引用,

class InnerClass{
        public int data1 = 11111;
        public int data4 = 4;
        private int data5 = 5;
        public static int data6 = 6;
        public void test(){
            System.out.println(data1);
			System.out.println(this.data1);//我們加上了this引用,這個時候表明這個data1是哪一類中的
			System.out.println(OutClass1.this.data1);   
            System.out.println(data5);
            System.out.println("內部類的test方法");
        }
}

這個this就表明當前誰在調用這個內部類的成員變量,然后我們用外部類的this

那么可能會有人說,在外部類的方法中去訪問內部類的成員,我們可以先來看一下:

//這個時候IDEA也就會自動爆紅,顯示出錯,但是我們也可以來運行一下代碼,但是也會發(fā)現(xiàn)它們會報錯;

因為這個data4是在內部類中,我們沒有內部類的實例化,外部類是無法訪問的其內部類中的成員變量的

所以我們需要先進行內部類的實例化才可以執(zhí)行這個代碼:

public void test(){
        System.out.println("外部類的test方法");
        //訪問內部類成員:
        /*System.out.println(data4);//這就報錯了*/
        InnerClass innerClass = new InnerClass();
        System.out.println(innerClass.data4);
}

這個時候我們會發(fā)現(xiàn)內部類在外部類中的實例化的時候居然與普通的類進行實例化是一樣的

總結:
獲取實例內部類的對象的時候,依賴于外部類的對象;
要獲得實例內部類對象,一定要先有外部類對象的訪問。

這個時候我們前面的代碼在內部類中提到了一個靜態(tài)成員變量data6這個時候我們可以看一下這個代碼行的結果:

//外部類中也有靜態(tài)成員
class InnerClass{
        public int data1 = 11111;
        public int data4 = 4;
        private int data5 = 5;
        public static int data6 = 6;
        public void test(){
            System.out.println(data1);
            System.out.println(data5);
            System.out.println("內部類的test方法");
        }
}

等待我們執(zhí)行完成后會發(fā)現(xiàn)出現(xiàn)了錯誤,

因為static修飾的成員是不依賴于類本身,并且是最先執(zhí)行的,而實例內部類確實需要依賴于外部類的對象,實例內部類是沒有獨立的儲存空間來儲存靜態(tài)成員,如果直接用static修飾的話,會造成外部類的執(zhí)行在加載的時候,導致訪問靜態(tài)成員會比較混亂,靜態(tài)成員是屬于類的,所以用final修飾我們可以確定是一個常量,并且表示對于開發(fā)者和編譯器來說這只有一個這樣的靜態(tài)成員

所以我們最后應該寫成:

public static final int data6 = 6;

通過類名進行訪問,我們可以得到這樣的結果:

2.(2).靜態(tài)內部類

靜態(tài)內部類就是在普通的類中用static來定義一個類

class OutClass2 {
    public int data1 = 1;
    public int data2 = 2;
    public static int data3 = 3;
    
    static class InnerClass{
        public int data4 = 4;
        private int data5 = 5;
        public static int data6 = 6;
        public void test(){
            System.out.println(data1);
            System.out.println("內部類的test方法");
        }
    }
}

這個時候我們看到這個靜態(tài)類中還有非靜態(tài)成員,但是我們用類名訪問只能是靜態(tài)成員和靜態(tài)方法,所以我們還需要把這個靜態(tài)類進行實例化:

public class Test2 {
    public static void main(String[] args) {
        OutClass2.InnerClass innerClass = new OutClass2.InnerClass();
        innerClass.test();
    }
}

雖然我們把靜態(tài)內部類進行實例化,但是我們還需要訪問內部類中的靜態(tài)成員最好還是用類名進行訪問

我們執(zhí)行完了這個程序后,發(fā)現(xiàn)了報錯,我們在靜態(tài)內部類無法直接訪問外部類的非靜態(tài)成員變量

所以我們也可以在靜態(tài)內部類中進行實例化外部類,從而去訪問它的成員變量

static class InnerClass{
        public int data4 = 4;
        private int data5 = 5;
        public static int data6 = 6;
        public void test(){
            OutClass2 outClass2 = new OutClass2();
            System.out.println(outClass2.data1);
            System.out.println(data4);
            System.out.println(data5);
            System.out.println(data6);
            System.out.println("內部類的test方法");
        }
}

執(zhí)行完后我們可以看到,可以直接打印出來

我們會看到兩個特殊的變量:靜態(tài)變量data3和data6兩者

在外部類中也可以直接用內部類的類名訪問其中的靜態(tài)成員變量data6

但是我們在靜態(tài)內部類中可以直接訪問外部類中的靜態(tài)成員變量data3

static class InnerClass{
        public int data4 = 4;
        private int data5 = 5;
        public static int data6 = 6;
        public void test(){
            System.out.println(data3);
        }
}

在靜態(tài)內部類中我們可以直接訪問外部類中的靜態(tài)成員變量,非靜態(tài)成員需要將外部類進行實例化,才可以進行訪問。

2.(3).匿名內部類

匿名內部類是沒有類名的一種類,但是前提也是根據(jù)接口,來實現(xiàn)的

那么我們需要首先定義一個接口:

interface A{
    void testA();
}
public class Test2 {
    public static void main(String[] args) {
        new A(){
            @Override
            public void testA() {
                System.out.println("X!");
            }
        }
    }
}

這種方式就是匿名內部類,這時候我們發(fā)現(xiàn)這個類沒有名字,實現(xiàn)了接口A,也重寫了接口A中的方法

那么這種類怎么去調用呢?

我們可以在尾大括號后加入了.testA(),便可以調用這個類

當然我們可以像類一樣去進行接口的**“實例化”**,得到了也是匿名內部類,

public class Test2 {
    public static void main(String[] args) {
        int val = 10;
        A a = new A() {
            @Override
            public void testA() {
                System.out.println("值:" + val);
            }
        };
        a.testA();
        System.out.println(val);
    }
}

去定義一個接口,去實現(xiàn)這個方法,但是我們依舊發(fā)現(xiàn)了這個類沒有名字

正常類應該有class來定義,這里面的類沒有用class來定義,所以它依舊是匿名內部類

如果我們這個時候去修改val的值,會發(fā)生什么呢?

public class Test2 {
    public static void main(String[] args) {
        int val = 10;
        val = 100;
        A a = new A() {
            @Override
            public void testA() {
                System.out.println("值:" + val);
            }
        };
        a.testA();
        System.out.println(val);
    }
}

可是執(zhí)行完之后我們發(fā)現(xiàn)它報錯了。

因為在匿名內部類當中能夠訪問的是沒有被修改過的數(shù)據(jù)
這種限制叫做變量的捕獲
所以默認在匿名內部類中能訪問的是被final修飾的變量,隱式的

2.(4).局部內部類

局部內部類:定義在方法的內部

它不能被public,static等訪問限定符修飾

編譯器也有自己獨立的字節(jié)碼文件,命名格式:外部類名字$數(shù)字內部類名字.class

這種類只能在方法體中使用:

public class Test4 {
    public void func(){
        class Inner{
            public int data = 1;
        }
        Inner inner = new Inner();
        System.out.println(inner.data);
    }
    public static void main(String[] args) {
        Test4 test4 = new Test4();
        test4.func();
        System.out.println();
    }
}

我們在日常中很少用到局部內部類,所以我們在這里不太過深入進行講解。

總結

到此這篇關于Java中Object和內部類的文章就介紹到這了,更多相關Java Object和內部類內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java實現(xiàn)文件上傳下載功能

    java實現(xiàn)文件上傳下載功能

    這篇文章主要介紹了java實現(xiàn)文件上傳下載功能,上傳單個或多個文件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • QueryWrapper中or的使用技巧分享

    QueryWrapper中or的使用技巧分享

    在日常的開發(fā)工作中,處理數(shù)據(jù)庫查詢是一個非常常見的任務,尤其是當我們需要在復雜條件下篩選數(shù)據(jù)時,如何編寫高效、簡潔且可維護的查詢邏輯顯得尤為重要,本文給大家介紹了QueryWrapper中or的使用技巧,需要的朋友可以參考下
    2024-10-10
  • Eclipse中引入com.sun.image.codec.jpeg包報錯的完美解決辦法

    Eclipse中引入com.sun.image.codec.jpeg包報錯的完美解決辦法

    Java開發(fā)中對圖片的操作需要引入 com.sun.image.codec.jpeg,但有時引入這個包會報錯,利用下面的操作可以完成解決這個問題
    2018-02-02
  • Spring中使用事務嵌套時需要警惕的問題分享

    Spring中使用事務嵌套時需要警惕的問題分享

    最近項目上有一個使用事務相對復雜的業(yè)務場景報錯了。在絕大多數(shù)情況下,都是風平浪靜,沒有問題。其實內在暗流涌動,在有些異常情況下就會報錯,這種偶然性的問題很有可能就會在暴露到生產(chǎn)上造成事故,那究竟是怎么回事呢?本文就來簡單講講
    2023-04-04
  • Java微信公眾平臺開發(fā)(2) 微信服務器post消息體的接收

    Java微信公眾平臺開發(fā)(2) 微信服務器post消息體的接收

    這篇文章主要為大家詳細介紹了Java微信公眾平臺開發(fā)第二步,微信服務器post消息體的接收,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • RabbitMQ 集群部署方法

    RabbitMQ 集群部署方法

    文章主要介紹了RabbitMQ在三臺CentOS7服務器上的安裝和集群配置,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2026-04-04
  • Spring XML Schema擴展機制的使用示例

    Spring XML Schema擴展機制的使用示例

    所謂整合,即在Spring的框架下進行擴展,讓框架能無縫的與Spring工程配合使用。Spring設計了良好的擴展的機制,本文將對Spring的擴展方法及原理進行簡單介紹。
    2021-05-05
  • idea中誤刪*.iml的問題解決辦法

    idea中誤刪*.iml的問題解決辦法

    *.iml是IntelliJ IDEA中的模塊配置文件,當丟失此文件時,項目可能出現(xiàn)錯誤,解決辦法是在項目目錄下執(zhí)行mvn idea:module命令來重新生成,下面就來具體介紹一下
    2025-08-08
  • Spring事務的失效場景你知道多少

    Spring事務的失效場景你知道多少

    這篇文章主要為大家詳細介紹了Spring事務的失效場景,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • quarzt定時調度任務解析

    quarzt定時調度任務解析

    這篇文章主要介紹了quarzt定時調度任務,具有一定參考價值,需要的朋友可以了解下。
    2017-12-12

最新評論

安徽省| 浪卡子县| 策勒县| 全椒县| 阿合奇县| 灌阳县| 黔江区| 道孚县| 雅江县| 公安县| 克山县| 邢台市| 和龙市| 石家庄市| 晋城| 泽库县| 祁连县| 皋兰县| 河源市| 永寿县| 萨迦县| 贡觉县| 华容县| 云龙县| 克什克腾旗| 邵阳县| 全州县| 华阴市| 西乌| 兴安盟| 利津县| 平昌县| 康马县| 怀来县| 景宁| 海原县| 南江县| 科技| 怀安县| 韩城市| 江安县|