Integer.valueof()學習之享元模式

小鞅發表於2016-04-19

問題描述:

1. Integer類初始化

//當這樣定義integer的引用初始化為3的時候,則會自動呼叫Integer類的valueof()方法,與Integer i=Integer.valueof(3)等價
1.Integer i=3;
//這種定義與初始化方式與上一種方式不一樣,效率比上一種效率低
2.Integer i=new Integer(3);

2.Integer 類比較

public static void test() {
        Integer a1 = 3;
        Integer b1 = Integer.valueOf(3);

        Integer a2 = 200;
        Integer b2 = Integer.valueOf(200);

        if (a1 == b1) {
            System.out.println("a1=b1");
        } else {
            System.out.println("a1!=b1");
        }
        if (a2 == b2) {
            System.out.println("a2==b2");
        } else {
            System.out.println("a2!=b2");
        }

    }

輸出結果:

a1=b1
a2!=b2

輸出結果不一樣,這是為什麼呢?
我們先看一下valueof()的原始碼


相關設計模式:享元模式


    public static Integer valueOf(String s) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, 10));
    }


//下面會解釋
       public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

private static class IntegerCache {

        //設定快取中陣列元素的最小值,而不是下標
        static final int low = -128;
        //快取的最大值
        static final int high;
        //定義一個Integer陣列
        static final Integer cache[];

        static {
            // 設定快取的最大值
            int h = 127;
            //這裡靜態塊先不用看,他是可以通過設定jdk的AutoBoxCacheMax引數調整來獲取最大值h,自動快取區間設定為[-128,h]。
            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;

            //設定快取的大小為256
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                //在陣列下標為0-255的陣列中預先存入-128~127的元素值,這裡就用到了享元模式,預先將-128-127存入陣列當中,當要用的時候直接取出來
                cache[k] = new Integer(j++);

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

現在我們來解釋這段程式碼就能看明白

//當i的值-128<i<127的時候,直接從cache陣列中取出對應i值的引用(注意是引用),當i>127或者i<-128的時候,則重新建立一個Integer(i)物件
 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

問題1的解釋:


1.Integer i=3;
2.Integer i=new Integer(3);

當這樣定義integer的引用初始化為3的時候,則會自動呼叫Integer類的valueof()方法,因為3在cache[256](cache[0]=-128,cache[1]=-127 ….. cache[256]=128)陣列中,所以返回時直接3對應的引用,而不用new Integer(3)重新建立一個音樂,所以Integer i=3效率高

問題2解釋:

與解釋1原理是一樣的,

        Integer a1 = 3;
        Integer b1 = Integer.valueOf(3);
        Integer a2 = 200;
        Integer b2 = Integer.valueOf(200);

即使Integer a2 = 200;呼叫了valueof()方法,但是200>128,此時cache陣列中沒有200這個值,因此只能採用new Integer()重新建立Integer物件了,這這裡連續建立了兩個物件,他們的引用是不一樣的,因此a2!=b2(==表示的是引用)。

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>

相關文章