Integerキャッシュメカニズム分析

12540 ワード

JAvaのIntegerキャッシュメカニズム分析:
Integerを例として梱包と解体について説明する:「梱包が存在する場合:intがIntegerすなわち基本タイプに梱包タイプに付与された場合
Integer i = 1; Integer i=Integer.valueOf(1)に等しい.JAva自動梱包作業完了
解体ケースが存在する場合:intとIntegerの比較及び基本タイプと包装タイプの比較時
Integer i = new Integer(1);
int j = 1;
i == j  //    i.intValue() == j  i       int   j    

Integerの原理とキャッシュメカニズム
Integerはint基本データ型のパッケージクラスであり、int基本型に基づいていくつかの操作とその他の属性を追加したにほかならない.
private final int value;//  int               
 public int intValue() {
        return value;
 }

前述した梱包の1つの方法はvalueOf()です.ソースコードを見てみましょう.
//       i   IntegerCache    IntegerCache    IntegerCache  Integer    new  Integer  
 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

IntegerCacheは以下のように実現される.
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) {
            int i = parseInt(integerCacheHighPropValue);
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - (-low));
        }
        high = h;
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }
    private IntegerCache() {}
}

Integerキャッシュが存在することを知っています.次に、以下の例を見てみましょう.注:==オブジェクトの比較は、オブジェクトの参照が等しいかどうかequalsは、オブジェクト内部の実装状況に応じて比較されます.
Integer i = 1; //i = Integer.valueOf(1)       IntegerCache.cache[129]
Integer j = 1; //j = Integer.valueOf(1)       IntegerCache.cache[129]
System.out.println(i == j);//  true  i  j        
Integer i = 1; //i = Integer.valueOf(1)       IntegerCache.cache[129]
Integer j = new Integer(1); //        
System.out.println(i == j);//  false i  j          
Integer i = 128; //i = Integer.valueOf(128)         new Integer(128)
Integer j = 128; //j = Integer.valueOf(128)         new Integer(128)
System.out.println(i == j); //  false i  j           

だからIntegerオブジェクトは比較が等しいかどうかの時==equals Integer内部で自分がequalsを使うことを実現して、ソースコードは以下の通りです:
public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
}

Integerキャッシュのデフォルト範囲は-128127であり、IntegerCache.highで最大の範囲を設定できることがわかります.この部分はstaticなので、クラスをロードするとIntegerキャッシュが初期化され、その後、範囲内のすべてのIntegerがこのキャッシュ配列static final Integer cache[]から来ている限り.
まとめ:
Integer値判定を行うには,==を使用するのではなくequalsを使用すべきであり,これにより奇妙なエラー(キャッシュ範囲で失効しない)を回避できることがわかる.