之前我們比較基本數(shù)據(jù)類型的方式很簡(jiǎn)單,1==1,true == true ,2 == 3,通過“==”的方式比較兩個(gè)數(shù)據(jù)是否相等。
但是之前,我們使用包裝類包裝了兩個(gè)數(shù)據(jù),比較這兩個(gè)包裝類的時(shí)候,我們發(fā)現(xiàn),即便包裝的數(shù)據(jù)一樣,但是使用“==”返回false。
class EqualsTest{ publicstatic void main(String[] args){ Personp1 = new Person("小明","帝都",28); Personp2 = new Person("大明","魔都",22); System.out.PRintln(p1== p2);//false Personp3 = new Person("大明","魔都",22); System.out.println(p3== p2);//false Integerinteger1 = new Integer(1); Integerinteger2 = new Integer(1); System.out.println(integer2== integer1);//false }} class Person{ publicPerson(String name ,String address ,int age){ this.name= name; this.address= address; this.age= age; } Stringname ; Stringaddress; int age;}我們?cè)诒容^基本數(shù)據(jù)類型時(shí),可以直接使用==來判斷是否相等。
但是,引用數(shù)據(jù)類型,不可以使用==來判斷,即便,兩個(gè)引用類型指向的對(duì)象屬性完全一致,但是依然返回false。
這是因?yàn)椋簩?duì)象使用“==”比較的話,比較的是引用所指向?qū)ο蟮牡刂?#20540;,比較是對(duì)象是否同一個(gè)。如下案例,當(dāng)兩個(gè)引用變量指向同一個(gè)對(duì)象,再比較的話,就是true,因?yàn)閮蓚€(gè)變量的引用都是指向同一個(gè)對(duì)象,所以比較的地址值也一樣,所以返回true。否則,返回false.
class EqualsTest{ publicstatic void main(String[] args){ Personp1 = new Person("小明","帝都",28); Personp2 = p1; System.out.println(p1== p2);//true }} class Person{ publicPerson(String name ,String address ,int age){ this.name= name; this.address= address; this.age= age; } Stringname ; Stringaddress; int age;}但是,在開發(fā)中,我們經(jīng)常會(huì)遇到一種問題,就是我們需要把屬性相同的兩個(gè)對(duì)象認(rèn)為是同一個(gè)對(duì)象。這個(gè)時(shí)候,我們使用equals方法來解決這種問題。
比較兩個(gè)對(duì)象,Object類提供了equals方法供我們自定義比較兩個(gè)對(duì)象是否相等。在定義類的時(shí)候,我們可以重寫該方法,來達(dá)到自定義判斷兩個(gè)對(duì)象是否相等的目的。當(dāng)對(duì)象調(diào)用equals方法的時(shí)候,就會(huì)執(zhí)行該對(duì)象重寫的equals方法來判斷與傳入的對(duì)象是否是同一個(gè)對(duì)象,這樣就達(dá)到了手動(dòng)控制的目的。
但是,如果沒有重寫equals方法,那么就是執(zhí)行默認(rèn)的object提供的equals方法。

我們翻開原碼發(fā)現(xiàn),默認(rèn)的提供的equals方法,其實(shí)就是使用==來比較兩個(gè)對(duì)象,比較的是指向的對(duì)象的地址值。當(dāng)我們沒有重寫equals方法,執(zhí)行該方法實(shí)際就是執(zhí)行了==運(yùn)算,比較兩個(gè)對(duì)象的地址值是否同一個(gè)。


一般來說,java提供的很多類都重寫了equals方法,用來判斷。
練習(xí):
class EqualsTest{ public static void main(String[] args){ Person p1 = new Person("小明","帝都",28); Person p2 = new Person("大明","魔都",22); System.out.println(p1.equals(p2));//false Person p3 = new Person("大明","魔都",22); System.out.println(p3.equals(p2));//true }} class Person{ public Person(String name ,String address ,int age){ this.name= name; this.address= address; this.age= age; } public boolean equals(Object obj) { //判斷地址是否一樣 if(this== obj){ retur ntrue; } //判斷傳入的對(duì)象引用是否為null if(obj== null){ return false; } //判斷傳入的對(duì)象是否該屬于本類類型對(duì)象 if(!(obj instanceof Person)){ return false; } //將傳入對(duì)象強(qiáng)轉(zhuǎn) Person ap = (Person)obj; //依次判斷傳入對(duì)象的屬性與本對(duì)象屬性是否一致 //判斷name if(this.name== null){ if(ap.name!=null){ return false; } }else{ if(!this.name.equals(ap.name)){ return false; } } //判斷age if(this.age!= ap.age){ return false; } //判斷address if(this.address== null){ if(ap.address!=null){ return false; } }else{ if(!this.name.equals(ap.name)){ return false; } } //到這一步,說明所有屬性都相同 return true; } String name ; String address; int age;}toString方法:(自定義打印對(duì)象內(nèi)容)
有的時(shí)候,我們需要知道一下對(duì)象的內(nèi)容,那么我們將對(duì)象打印輸出查看,但是我們直接輸出的話,打印結(jié)果如下:

我們發(fā)現(xiàn),這個(gè)結(jié)果并不是我們需要的。假設(shè)我們需要打印對(duì)象,打印對(duì)象的內(nèi)容如屬性,那么這個(gè)時(shí)候,我們需要自定義一下打印的內(nèi)容。
Object類提供了默認(rèn)方法toString方法,該方法返回該對(duì)象的字符串表示形式。他默認(rèn)打印的是對(duì)象的類型+@+哈希值。當(dāng)我們需要自定義對(duì)象的字符串表現(xiàn)形式時(shí),我們可以重寫toString方法。
如下:object類中源碼默認(rèn)打印:
public String toString() { return getClass().getName() + "@" +Integer.toHexString(hashCode()); }我們發(fā)現(xiàn),直接打印對(duì)象,就會(huì)默認(rèn)調(diào)用該對(duì)象的toString方法,打印該方法的返回值。
class EqualsTest{ public static void main(String[] args){ Person p1 = new Person("小明","帝都",28); //直接打印對(duì)象,就是打印對(duì)象toString方法返回值 System.out.println(p1); Person p2 = new Person("大明","帝都",22); System.out.println(p2.toString()); }} class Person{ public Person(String name ,String address ,int age){ this.name= name; this.address= address; this.age= age; } public String toString(){ Stringresult = "name:" + name +";address:" + address+";age:" + age; return result; } public boolean equals(Object obj) { //判斷地址是否一樣 if(this== obj){ return true; } //判斷傳入的對(duì)象引用是否為null if(obj== null){ return false; } //判斷傳入的對(duì)象是否該屬于本類類型對(duì)象 if(!(obj instanceof Person)){ return false; } //將傳入對(duì)象強(qiáng)轉(zhuǎn) Person ap = (Person)obj; //依次判斷傳入對(duì)象的屬性與本對(duì)象屬性是否一致 //判斷name if(this.name== null){ if(ap.name!=null){ return false; } }else{ if(!this.name.equals(ap.name)){ return false; } } //判斷age if(this.age!= ap.age){ return false; } //判斷address if(this.address== null){ if(ap.address!=null){ return false; } }else{ if(!this.name.equals(ap.name)){ return false; } } //到這一步,說明所有屬性都相同 return true; } String name ; String address; int age;}
哈希值:
在之前,我們翻開Object的源碼發(fā)現(xiàn),會(huì)打印類名+@+哈希值。
那么哈希值到底是什么東西?
每個(gè)對(duì)象,都會(huì)有一個(gè)唯一的哈希值,當(dāng)使用“==”比較兩個(gè)對(duì)象,其實(shí)比較的就是哈希值!
哈希值是當(dāng)創(chuàng)建對(duì)象后,由虛擬機(jī)自動(dòng)生成,無法更改。
當(dāng)然,每個(gè)對(duì)象也提供了獲取哈希值的方法hashCode方法,默認(rèn)返回的就是哈希值。
該方法是Object提供的,可以重寫該方法。
什么時(shí)候需要用到重寫該方法?
在之后課程集合中,判斷一些對(duì)象是否重復(fù),用到哈希值,重寫hashCode方法。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注