Why does Integer provide a valueOf(xx) method with the same function as new Integer(xx). After reading the source code, I found an amazing inside story.
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); // if there is no cache, new }
It turns out that a static inner class IntegerCache is defined in the Integer 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) { 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); } 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 {} }
After the class is loaded, several Integer objects will be cached in the memory, the default is from -128 to 127, and high can be configured (XX:AutoBoxCacheMax=200). Call valueOf(x), when x>=-128 and x<=high, directly fetch the object in the cache (heap), without new, if it is not in this range, new. We know that autoboxing (int->Integer) will occur when Integer a = 12, which actually calls Integer.valueOf(12), which is verified by javap as follows:
localhost:tmp javahongxi$ javap -c T Warning: binary file T contains tmp.T Compiled from "T.java" public class tmp.T { java.lang.Integer i; public tmp.T; Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":V 4: aload_0 5: bipush 12 7: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 10: putfield #3 // Field i:Ljava/lang/Integer; 13: return }
At this point, we can draw an important conclusion: For integers in the range of -128~127, we must never declare them with new Integer, please use automatic boxing or Integer.valueOf.
Finally we look at the equals method,
private final int value; public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue; } return false; }
Now, we should be able to deal with all kinds of written test questions about Integer== judgment.