關於java的自動包裝機制想必大家都用過吧,一般這些機制都用於在往容器中存儲基本類型數據的時候,因為容器中不允許存在基本數據類型,所以就會調用自動包裝機制,將基本數據類型轉換為對象,將基本數據保存在對象中,並且提供一些基本方法,但是自動包裝機制存在一些陷阱,使用不當就會出錯
先看看下面一個例子吧
1 package test; 2 3 public class AutoPack { 4 public static void main(String[] args) { 5 Integer a=1; 6 Integer b=2; 7 Integer c=3; 8 Integer d = 3; 9 Integer e=321; 10 Integer f=321; 11 Long g=3L; 12 System.out.println(c==d);//true 13 System.out.println(e==f);//false 14 System.out.println(c==(a+b));//true 15 System.out.println(c.equals(a+b));//true 16 System.out.println(g==(a+b));//true 17 System.out.println(g.equals(a+b));//false //不是同一類型 18 System.out.println(g.equals((long)(a+b)));//true 首先比較是不是同一類型,再比較值 19 } 20 }
上面例子中的輸出你都做對了嗎?如果有疑惑,請看我下面的解答
首先我們得請出一個前提:對於對象類型,==符號表示比較對象的所在的物理地址,equals方法比較的是對象的值(前提是兩者屬於同一個對象類型),而對於基本數據類型,==符號比較的是值
然后我們再來看一看Integer的內部實現,Integer有三種創建方法,分別是
Integer a = new Integer(1); //創建新的類 Integer b = Integer.valueOf(2); Integer c = 3; //自動包裝,會調用valueOf方法
上面的三種方法中,第一種方法所創建的是一個全新的Integer對象,這樣的對象在用 == 比較時是肯定不相同的,只能通過 equals 方法進行比較
,第二種方法和第三種方法都顯式或者隱式的調用了ValueOf方法,所以下面我們來看一下ValueOf方法
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
valueOf方法首先判斷數字是否大於low(-128)並且小於數字(127),如果滿足條件,則直接從IntegerCache中返回這個數(IntegerCache用於存儲一些常用的數,防止重復創建),
所以只要是用 valueOf 或者Integer = num 這兩種方法創建的對象,其值小於127且大於-128的,無論對其進行 == 比較還是equals 比較,都是true
對於不滿足這個范圍的數,無論怎么創建,都是一個新的對象,是只能通過equals比較的,接下來我們再看看equals方法
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
equals很簡單,首先比較兩者的類型是否一致,如果類型不一致,直接返回false,否則,再比較兩者的值,相同則返回true
那么現在你再回過頭去看上面的輸出,是不是清晰明了呢
還有一點就是上面的第三個和第五個輸出了,因為等式兩邊都運用了算術運算符,所以會自動拆包,拆包后比較的就是兩者的value了
那么下面來總結一下:
1.在==運算的時候,如果兩端中任何一端含有算術表達式,就會發生自動解包,這時比較的是值
2.在==運算時,兩端都沒有算術表達式,就不會解包,這時比較的是對象的地址(這樣使用很危險)
3.equals可以比較對象的值,比較推薦使用,但前提是要相同對象類型,比如在上面倒數第二個輸出中,雖然值相等,但是一個是Integer,一個是Long,就會返回false,但是如果是基本數據類型int 和 long ,他們其實是可以相等的
4.Integer中有IntegerCache,會對-128到127的值進行緩存,所以在這個范圍內只要不用new 關鍵字創建Integer對象,那么這些對象都是同一個對象