在Java中,Integer封裝類的相等性比較常常讓人感到困惑。為什么當(dāng)我們比較100和100時,結(jié)果為true,但比較1000和1000時,結(jié)果卻為false?這個現(xiàn)象涉及到Java的整數(shù)緩存和對象引用的差異。在本文中,我們將揭示這個有趣的現(xiàn)象的原因,并解釋如何正確比較整數(shù)封裝類的相等性。
在Java中,對于整數(shù)類型的封裝類Integer,我們經(jīng)常會遇到一個有趣的現(xiàn)象:當(dāng)比較兩個小整數(shù)相等性時,例如100和100,結(jié)果為?true
?;但當(dāng)比較兩個大整數(shù)相等性時,例如1000和1000,結(jié)果卻為?false
?。這種現(xiàn)象背后隱藏著Java中整數(shù)對象緩存和對象引用的一些細(xì)微差別。
public class Main {
public static void main(String[] args) {
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b);
Integer c = 100;
Integer d = 100;
System.out.println(c == d);
}
}
/**
* 運(yùn)行結(jié)果
* false
* true
*/
為了提高性能和節(jié)省內(nèi)存,Java在內(nèi)部維護(hù)了一個整數(shù)緩存池,范圍是-128到127。當(dāng)我們創(chuàng)建一個Integer對象時,如果數(shù)值在這個范圍內(nèi),Java會嘗試從緩存池中獲取已經(jīng)存在的Integer對象。這樣,當(dāng)我們使用相同數(shù)值的兩個Integer對象進(jìn)行比較時,它們實(shí)際上是同一個對象的引用,因此比較結(jié)果為?true
?。這種情況下,我們可以說它們是相等的。
然而,當(dāng)整數(shù)超出了緩存池的范圍,例如1000,Java會在堆中創(chuàng)建新的Integer對象,而不是從緩存池中獲取。盡管它們的數(shù)值相同,但它們在內(nèi)存中是不同的對象,具有不同的引用。因此,當(dāng)我們比較兩個大整數(shù)的相等性時,由于比較的是對象的引用而不是數(shù)值本身,結(jié)果為?false
?。
這種行為可以通過Java的自動裝箱(Autoboxing)和拆箱(Unboxing)機(jī)制來解釋。當(dāng)我們使用?==
?運(yùn)算符比較兩個Integer對象時,實(shí)際上是在比較它們的引用,而不是數(shù)值。如果我們想要比較它們的數(shù)值是否相等,應(yīng)該使用?equals()
?方法,因?yàn)樵贗nteger類中,?equals()
?方法被重寫以進(jìn)行數(shù)值的比較。
public class Main {
public static void main(String[] args) {
Integer a = 1000;
Integer b = 1000;
System.out.println(a.equals(b));
Integer c = 100;
Integer d = 100;
System.out.println(c == d);
}
}
/**
* 運(yùn)行結(jié)果
* true
* true
*/
需要注意的是,這種整數(shù)緩存的行為只適用于整數(shù)類型的封裝類Integer,而不適用于其他封裝類如Long、Double等。
為了避免這種混淆和潛在的錯誤,我們應(yīng)該始終使用?equals()
?方法來比較兩個封裝類的相等性,尤其是在使用自動裝箱和拆箱的情況下。此外,如果我們需要比較大整數(shù)的相等性,建議使用?equals()
?方法或?qū)⒄麛?shù)轉(zhuǎn)換為基本數(shù)據(jù)類型進(jìn)行比較。
總結(jié)
Java中的整數(shù)封裝類Integer存在一個緩存池,對于-128到127之間的整數(shù),它們是同一個對象的引用,因此比較結(jié)果為true;對于超出該范圍的整數(shù),它們是不同的對象,比較結(jié)果為false。這是由于自動裝箱和對象引用的特性所導(dǎo)致的,我們應(yīng)該謹(jǐn)慎使用==運(yùn)算符來比較封裝類的相等性,而是使用equals()方法來進(jìn)行數(shù)值的比較。