有趣的Java之包裝類型的緩存與"==" equals


在進入正文之前 , 我們寫來看一段代碼

public static void main(String[] args) {
Integer i1 = 127;
Integer i2 = 127;
Integer i3 = new Integer(127);
System.out.println("one==:" + i1 == i2);
System.out.println("one2==:" + i1 == i3);
System.out.println("twoeq:"+i1.equals(i3));
System.out.println("threq:"+i1.equals(i2));
i1 = 128;
i2 = 128;
System.out.println("four==:" + i1 == i2);
System.out.println("fiveq:" + i1.equals(i2));
}

分析這段代碼 , 按照我們原來的想法 , 由於在比較對象為基本數據類型時 , “==”比較的是值是否相等 , 但是 Integer 是 int 的包裝類 , 它是一個對象 , 所以 “==” 在這里和 equals 一樣比較的是對象的引用是否相同 .
粗略一看 , 好像他們的輸出應該全為 false , 因為它們都創建了新的對象 .
的確 , 如果是其他對象的話 , 我們的猜想是沒有錯的 , 但是包裝類型不一樣 .
equals 在 包裝類型和 String 類中被重寫了 , 比較的是值是否相等
Object equals 方法實現如下:

public boolean eqauls(Object obj){
return (this == obj);
}

在包裝類型中重寫 :

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

可以看到 , java 將 Object 幫我們轉換成了 Integer(對應包裝類) , 然后通過 Integer.intValue() 與 value(其值)使用 “==” 進行比較 , 結果自然而然是 true

接下來我們看看equals 在 String 中的重寫

 public boolean equals(Object anObject) {
//如果引用相等
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
//將 value 和 與之相比的 value 值拆分為 char 一一比較
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

因此我們對最開始的那段程序有了新的結論 , 他的輸出應該是

one==:false
one2==:false
twoeq:true
threq:true
four==:false
fiveq:true

如果這個時候你心滿意足 , 那恭喜你得不到正確答案了

包裝類型除了重寫了 equals , 在后台還為我們做了一件事情 – 緩存 !
java 為了節省內存,設計了基本數據類型包裝類的緩存,就是程序啟動時,初始化的數值依次放在緩存池中,當你直接給 Integer 對象賦值時,它每次首先去緩存去查,如果有的話,直接將新 new 出的對象引用指向緩存池中的對象 ;
當然緩存池也不是無限大的 , Integer 緩存的范圍是[-128,127],超出范圍就需要重新在堆內存中new了,Byte 和 boolean 將全部緩存
所以我們運行最開始的程序的時候會發現 , 當 i1 , i2 為 128 時 , 輸出的是 false
終於真相大白了 , 所以它最后的輸出應該是 :

one==:true //緩存
one2==:false // i3 為新建對象 new Integer(127);
twoeq:true
threq:true
four==:false //超出緩存
fiveq:true

PS : java 雖然沒有對 String 做緩存 , 但是可以用 String.intern() 實現同樣效果


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com