首先看一段代碼(使用JDK 5),如下:
public class Hello { public static void main(String[] args) { int a = 1000, b = 1000; System.out.println(a == b); Integer c = 1000, d = 1000; System.out.println(c == d); Integer e = 100, f = 100; System.out.println(e == f); } }
輸出結果:
truefalsetrue
The Java Language Specification, 3rd Edition 寫道:
為了節省記憶體,對於下列封裝對象的兩個執行個體,當它們的基本值相同時,他們總是==: Boolean Byte Character, \u0000 - \u007f(7f是十進位的127) Integer, -128 — 127
查看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. During VM initialization the * getAndRemoveCacheProperties method may be used to get and remove any system * properites that configure the cache size. At this time, the size of the * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>. */ // value of java.lang.Integer.IntegerCache.high property (obtained during VM init) private static String integerCacheHighPropValue; static void getAndRemoveCacheProperties() { if (!sun.misc.VM.isBooted()) { Properties props = System.getProperties(); integerCacheHighPropValue = (String)props.remove("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) System.setProperties(props); // remove from system props } } private static class IntegerCache { static final int high; static final Integer cache[]; static { final int low = -128; // high value may be configured by property int h = 127; if (integerCacheHighPropValue != null) { // Use Long.decode here to avoid invoking methods that // require Integer's autoboxing cache to be initialized int i = Long.decode(integerCacheHighPropValue).intValue(); 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() {} } /** * Returns a <tt>Integer</tt> instance representing the specified * <tt>int</tt> value. * If a new <tt>Integer</tt> instance is not required, this method * should generally be used in preference to the constructor * {@link #Integer(int)}, as this method is likely to yield * significantly better space and time performance by caching * frequently requested values. * * @param i an <code>int</code> value. * @return a <tt>Integer</tt> instance representing <tt>i</tt>. * @since 1.5 */ public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); }
這兒的IntegerCache有一個靜態Integer數組,在類載入時就將-128 到 127 的Integer對象建立了,並儲存在cache數組中,一旦程式調用valueOf 方法,如果i的值是在-128 到 127 之間就直接在cache緩衝數組中去取Integer對象。
再看其它的封裝器:
- Boolean:(全部緩衝)
- Byte:(全部緩衝)
- Character(<= 127緩衝)
- Short(-128 — 127緩衝)
- Long(-128 — 127緩衝)
- Float(沒有緩衝)
- Doulbe(沒有緩衝)
同樣對於記憶體回收行程來說:
Integer i = 100; i = null;//will not make any object available for GC at all.
這裡的代碼不會有對象符合記憶體回收行程的條件,這兒的i雖然被賦予null,但它之前指向的是cache中的Integer對象,而cache沒有被賦null,所以Integer(100)這個對象還是存在。
而如果i大於127或小於-128則它所指向的對象將符合記憶體回收的條件:
Integer i = 10000; i = null;//will make the newly created Integer object available for GC.