一般我們使用數值時,都是使用基本類型,如int、long等,但如果你喜歡使用Integer、Long的包裝類,那有一點可就得注意了。先來看下這段代碼:
/** * * @author trytocatch@163.com * @date 2014-2-12 */ public class AutoBoxingTest { public static final Integer CONST_A = 1; public static final Integer CONST_B = Integer.valueOf("2"); public static final Integer CONST_C = new Integer(3); private Integer status; public void setStatus(Integer status){ this.status = status; } public void displayStatus(){ if(status == CONST_A) System.out.println("It's CONST_A"); else if(status == CONST_B) System.out.println("It's CONST_B"); else if(status == CONST_C) System.out.println("It's CONST_C"); else System.out.println("Invalid status!"); } public static void main(String[] args) { AutoBoxingTest abt = new AutoBoxingTest(); abt.setStatus(1); abt.displayStatus(); abt.setStatus(2); abt.displayStatus(); abt.setStatus(3); abt.displayStatus(); } }
執行結果是(jre版本:1.7.0_10):
It's CONST_A
It's CONST_B
Invalid status!
可能有人會奇怪,為什么第三個不輸出It's CONST_C呢?其實jre挺懶的,如果發現==兩邊都是對象,它就直接比較引用,而不是值,跟普通對象一樣,因為status為3的那次比較中,兩邊是兩個不同的對象,所以不相同。而前兩個為什么可以呢?是因為IntegerCache的存在,在自動裝箱(給CONST_A賦值和setStatus(int)時)和調用Integer.valueOf(String)時,返回的Integer有時(為什么說是有時?是因為IntegerCache只對部分數值做了緩存,具體請閱讀源碼)是從Cache中獲取的,所以都是同一個對象,而CONST_C在賦值時是我們自己new出來的,所以跟Cache中的對象不是同一個。
延伸一下,如果一邊是包裝類,一邊是基本類型時;或者使用了<、>、<=等比較符,都會進行值比較。只有剛好滿足引用比較的條件時,jre才會偷懶,直接進行引用比較。所以,定義常量變量時,最好使用基本類型,使用==和!=時多多留意。
ps:文章比較短,我不喜歡重復在網上隨便都能搜到的東西,像裝箱拆箱,封裝等。如果本文對你有幫助,還請支持一下
再啰嗦幾句,可能沒細看的讀者會覺得,不就是說==比較的是引用么,有什么好講的?我說下我寫此文的考慮,因為平時可能習慣了直接對封裝類使用<、>、<=等,使用==時也沒出問題(上面的例子中CONST_A和CONST_B那兩種情況),想當然的認為封裝類不會進行引用比較,這種觀念也許會在編碼中埋下隱患,如果你將CONST_A的值改為10000,你會發現又不對了。