當心Java中封裝類的值比較

    通常咱們使用數值時,都是使用基本類型,如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):this

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中的對象不是同一個。spa

    延伸一下,若是一邊是包裝類,一邊是基本類型時;或者使用了<、>、<=等比較符,都會進行值比較。只有恰好知足引用比較的條件時,jre纔會偷懶,直接進行引用比較。因此,定義常量變量時,最好使用基本類型,使用==和!=時多多留意。code

ps:文章比較短,我不喜歡重複在網上隨便都能搜到的東西,像裝箱拆箱,封裝等。若是本文對你有幫助,還請支持一下對象


再囉嗦幾句,可能沒細看的讀者會以爲,不就是說==比較的是引用麼,有什麼好講的?我說下我寫此文的考慮,由於平時可能習慣了直接對封裝類使用<、>、<=等,使用==時也沒出問題(上面的例子中CONST_A和CONST_B那兩種狀況),想固然的認爲封裝類不會進行引用比較,這種觀念也許會在編碼中埋下隱患,若是你將CONST_A的值改成10000,你會發現又不對了。blog

相關文章
相關標籤/搜索