遇到问题,最好的办法是写个Test类测试一下,再看源码
@Test
public void test() throws Exception {
Integer a = 127;
Integer b = 127;
Integer c = new Integer(127);
Integer d = new Integer("127");
Integer e = new Integer("127");
Integer x = 128;
Integer y = 128;
Long p = 128L;
Long q = 128L;
Long r = 127L;
Long s = 127L;
System.out.println(a==b);
System.out.println(x==y);
System.out.println(r==s);
System.out.println(p==q);
System.out.println(a==c);
System.out.println(c==d);
System.out.println(d==e);
}
执行结果是,除了a,b和r,s相等外,其余都为false
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" -ea -
true
false
true
false
false
false
false
new Integer(),new Long()与new String()一样,本质是开辟一个新的地址存储对象.
那 127组和128组为什么结果不一样呢?
当给Integer赋整数值的时候,实际是调用了java.lang.Integer#valueOf(int)方法
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
先查看是否落在缓存区间,如果在缓存区间,直接使用缓存,返回IntegerCache.cache[i + (-IntegerCache.low)],如果不在缓存空间,再new 一个.
,所以推测是 127这组落在了缓存区间,所以ab实际上取得同一个缓存地址,128没有落在缓存区间,new了一个新地址,所以结果不一样.我们来看源码
/** // 因为-128到127是常用的包装对象,所以在第一次使用的时候初始化并缓存到数组中
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
* // 可以通过参数-XX:AutoBoxCacheMax= 设置缓存大小
* 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;
// 可以通过参数java.lang.Integer.IntegerCache.high设置缓存最大值,设置时要注意
// -XX:AutoBoxCacheMax参数是否满足
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
// 取设置参数和默认127的最大值,但是也不能超过
// Integer.MAX_VALUE - (-low) -1
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() {}
}
静态内部类初始化的时候给缓存数组赋值,默认情况下,high为127,low是-128.
当给数组赋值a = 127时,用的是缓存cache[127+(-IntegerCache.low)]就是 cache[255],
而初始化时,cache的size是high-low+1为256,cache[255]就是数组的最后一个,即new Integer(127).
所以Integer a = 127,就是返回了缓存中的cache[255],所以每次都是返回缓存.地址相等.而128不在缓存中,就返回new Integer(128).地址不相等
Long也一样有静态缓存类LongCache,不过比起Integer更简单一些,直接设置了-128到127共256个缓存,当long类型落在缓存区间,使用==比较大小会相等.
private static class LongCache {
private LongCache(){}
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
当Long r = 127L时,实际是调用了Long.valueOf()方法自动装箱,先去拿缓存,如果没有再new Long()
/**
* Returns a {@code Long} instance representing the specified
* {@code long} value.
* If a new {@code Long} instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Long(long)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* Note that unlike the {@linkplain Integer#valueOf(int)
* corresponding method} in the {@code Integer} class, this method
* is <em>not</em> required to cache values within a particular
* range.
*
* @param l a long value.
* @return a {@code Long} instance representing {@code l}.
* @since 1.5
*/
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
但是,阿里巴巴开发规范手册强制要求使用equals比较,不推荐使用==比较 .