Java裝箱==的池化坑

原創作品,出自 “曉風殘月xj” 博客,歡迎轉載,轉載時請務必註明出處(http://blog.csdn.net/xiaofengcanyuexj)。

由於各種原因,可能存在諸多不足,歡迎斧正!

        今天讀《Effective Java》,讀到“基本類型優於裝箱基本類型” ,其中那個Integer例子覺得不合適,於是看了Integer源碼,發現還真是有點問題,至少我的jdk1.7是有問題的。

     Java是高度封裝基於JVM API的語言,和C++一個重要的區別就是不支持運算符重載。就我膚淺地理解,基本的運算操作+、-、*、/、==等對於開發者老說通常是不透明的,所以對於模糊的地方不好把握,對於裝飾器類型也就是通常意思的裝箱類型,如下:                                                             

int(4字節) Integer
byte(1字節) Byte
short(2字節) Short
long(8字節) Long
float(4字節) Float
double(8字節) Double
char(2字節) Character
boolean(未定) Boolean


        ==對於裝箱類型是不好把握的。以Integer爲例,通常在[-128,127](其中127取決於JDK中的)系統變量,具體如下:

 String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
 

    由於比較簡單,直接上實例代碼的

/**
 * @功能: Java測試類
 * @authord: jin.xu
 * @version: v1.0.0
 * @see:
 * @date: 2016/1/30 11:49
 */
public class Test {

    public static void main(String[] args) {
        Integer i=127;
        Integer j=127;

        if(j==i){
            System.out.println("true");
        }else{
            System.out.println("false");
        }


        Integer k=128;
        Integer t=128;
        if(k==t){
            System.out.println("true");
        }else{
            System.out.println("false");
        }

    }
}
輸入結果分別是:

true
false

      具體原因應該說是jdk還不能說是JVM將小範圍的數值做了緩存,如int的[-128,127](其中128並不是一個比較準確的答案),new對象的時候不是直接在堆上創建,而是從常量池中讀取,避免頻繁創建對象。我們知道,在堆上創建對象是有系統開銷的,而池化技術可以在一定程度上解決這類問題,如內存池、線程池等。當然,像jdk這類直接選定數值的方法也是比較粗糙的,還好其中的integerCacheHighPropValue 變量可以針對不同機器作調整。具體直接貼jdk代碼的

 /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }


     所以建議是對於裝箱類型,比較數值的時候最好直接使用equal()或者XXXValue()方法,避免使用運算符==。自己踩過或者躲過的坑,希望別人也不要踩。

    

     最近空閒時間有看源代碼的習慣,如雅虎基於在線機器學習開源爬蟲anthelion和dubbo的






               

  






      

            




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章