您好,登錄后才能下訂單哦!
這篇文章主要介紹“java==和equalse的區(qū)別是什么”,在日常操作中,相信很多人在java==和equalse的區(qū)別是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”java==和equalse的區(qū)別是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
1.總的來說==和equalse 比較的都是地址值;
2.==在對比基本數(shù)據(jù)類型和包裝類的常量池的時(shí)候,比較的是值
3.equalse是方法,只能作用于對象數(shù)據(jù)(Integer等封裝類也是對象哈),默認(rèn)也是比較地址值,但是大多數(shù)情況下我們是覆寫equalse方法來對比其屬性值是否一樣;
4.但是equalse方法可以被重寫。基本類型中封裝類Integer和String的equalse方法都是被重寫過的,所以比較的是值
5.Integer的常量池很好理解 -128 127,String也有常量池,我們字面創(chuàng)建String a=“xxx”這種都是進(jìn)入常量池
String的常量池說明可以參考這篇文章: https://www.cnblogs.com/tongkey/p/8587060.html
比較的是他們的值是否相等,比如兩個(gè)int類型的變量,比較的是變量的值是否一樣。
比較的是引用的地址是否相同,比如說新建了兩個(gè)User對象,比較的是兩個(gè)User的地址是否一樣。
基本類型的包裝類 也算是對象,不管是否使用常量池,只要一方通過new創(chuàng)建對象,那就一定是比較的地址值
以Integer舉例
不使用常量池:-128 127 public static void equalsTest(){ Integer A=new Integer(1); Integer B=new Integer(1);; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為:A!=B 使用常量池 public static void equalsTest(){ Integer A=new Integer(128); Integer B=new Integer(128);; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為:A!=B
以Integer舉例
在-128 127的時(shí)候,會使用常量池?cái)?shù)據(jù),從而比較對象值;不使用常量池的時(shí)候,會比較地址值
使用常量池的時(shí)候-128 127 public static void equalsTest(){ Integer A=-127; Integer B=-127;; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為:A=B 不使用常量池的時(shí)候,比較的是地址值 public static void equalsTest(){ Integer A=128; Integer B=128;; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為:A!=B
賦值128,沒有使用到常量池 public static void equalsTest(){ Integer A=new Integer(128); int B=128; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為:A=B 查看源碼 發(fā)現(xiàn) Integer只會對int作值的比較 /** * Compares this object to the specified object. The result is * {@code true} if and only if the argument is not * {@code null} and is an {@code Integer} object that * contains the same {@code int} value as this object. * * @param obj the object to compare with. * @return {@code true} if the objects are the same; * {@code false} otherwise. */ public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
我們通常使用String A="hello";這種方式創(chuàng)建的所有變量所有的都進(jìn)了字符串常量池
這種創(chuàng)建方式都是會使用到常量池 public static void equalsTest(){ String A="hello"; String B="hello"; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為: A=B 我們通常使用String A="hello";這種方式創(chuàng)建的所有變量所有的都進(jìn)了字符串常量池 String類的final修飾的,以字面量的形式創(chuàng)建String變量時(shí),jvm會在編譯期間就把該字面量(“hello”)放到字符串常量池中,由Java程序啟動的時(shí)候就已經(jīng)加載到內(nèi)存中了。這個(gè)字符串常量池的特點(diǎn)就是有且只有一份相同的字面量,如果有其它相同的字面量,jvm則返回這個(gè)字面量的引用,如果沒有相同的字面量,則在字符串常量池創(chuàng)建這個(gè)字面量并返回它的引用
3.5 String類型不使用常量池的情況,比較的是地址值
public static void equalsTest(){ String A="hello"; String B=new String("hello");; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為:A!=B 通過new創(chuàng)建對象,使用的是新的對象,結(jié)果自然不相等 public static void equalsTest(){ String A="hello"; String B=new String("hello"); //B引用變?yōu)槌A砍氐膆ello的引用 B=B.intern(); if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 輸出結(jié)果為:A=B
在大多數(shù)Java類庫中的類中 如基本類型中封裝類Integer和String的equalse方法都是被重寫過的,所以比較的是值
通常我們使用equalse都是自己覆寫方法來對比對象內(nèi)部的屬性值是否相同
結(jié)論:hashcode相同,值不一定相同,值相同hashCode一定相同(重寫hashCode方法)
hashCode是所有java對象的固有方法,如果不重寫的話,返回的實(shí)際上是該對象在jvm的堆上的內(nèi)存地址,而不同對象的內(nèi)存地址肯定不同,所以這個(gè)hashCode也就肯定不同了。如果重寫了的話,由于采用的算法的問題,有可能導(dǎo)致兩個(gè)不同對象的hashCode相同。
hashCode和equals兩個(gè)方法是有語義關(guān)聯(lián)的,它們需要滿足:
A.equals(B)==true --> A.hashCode()==B.hashCode()
因此重寫其中一個(gè)方法時(shí)也需要將另一個(gè)也重寫。
如果根據(jù) equals(Object) 方法,兩個(gè)對象是相等的,那么對這兩個(gè)對象中的每個(gè)對象調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。
3.1 hashCode的重寫實(shí)現(xiàn)需要滿足不變性,即一個(gè)object的hashCode不能前一會是1,過一會就變成2了。
3.2 hashCode的重寫實(shí)現(xiàn)最好依賴于對象中的final屬性,從而在對象初始化構(gòu)造后就不再變化。一方面是jvm便于代碼優(yōu)化,可以緩存這個(gè)hashCode;另一方面,在使用hashMap或hashSet的場景中,如果使用的key的hashCode會變化,將會導(dǎo)致bug,比如放進(jìn)去時(shí)key.hashCode()=1,等到要取出來時(shí)key.hashCode()=2了,就會取不出來原先的數(shù)據(jù)。
4.hashCode為什么會存在相同的情況
以hashSet舉例,hashSet JDK1.8以前底層結(jié)構(gòu)是數(shù)組+鏈表的形式,1.8之后是數(shù)組+鏈表+紅黑樹
以1.8舉例:
在向hashSet集合中添加元素時(shí),需要經(jīng)過兩個(gè)步驟
計(jì)算hashcode并與hashSet數(shù)組中的hashcode進(jìn)行比較
如果有相同的hashcode,則對該hash的內(nèi)容使用equals進(jìn)行比較,如果不同則存入集合
因此相同的hashcode不一定有相同的值,但是如果值相同,那他的hashcode一定相同
到此,關(guān)于“java==和equalse的區(qū)別是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。