小心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):

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,你會發現又不對了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM