装箱与拆箱
//手动装箱
Integer a=Integer.valueOf(10);
System.out.println("手动装箱"+a.intValue());
//自动装箱
Integer b=10; //自动调用valueof(10)方法
System.out.println("自动装箱"+b.intValue());
//手动拆箱
int c=a.intValue();
System.out.println("手动拆箱"+c);
//自动拆箱
int d=a; //自动调用a.intValue();
System.out.println("自动拆箱"+d);
结果
手动装箱10
自动装箱10
手动拆箱10
自动拆箱10
在算式表达式中
Integer n=3;
n++;
System.out.println("n="+n);
//编译器自动插入一条对象拆箱的指令,然后进行自增计算,最后再将结果装箱
结果
n=4
在条件表达式中混合使用Integer和Double
Integer s=1;
Double x=2.0;
System.out.println("条件表达式中s = "+(s<x?s:x));
//混合使用Integer和Double
//在条件表达式中,Integer值会拆箱,提升为Double,再装箱为Double
结果
条件表达式中s = 1.0
NULLPointerException
Integer n=null;
System.out.println(n+1);//throws NULLPointerException
//计算n+1中,n会自动拆箱(调用n.intValue())
//但是n为空,调用空对象的方法会抛出空指针异常(NULLPointerException)
Integer n=128; //等价于 Integer n=Integer.valueOf(128);
Integer s=128; //等价于 Integer s=Integer.valueOf(128);
System.out.println(" n == s "+(n==s));
System.out.println(" n equals s "+n.equals(s));
结果
n == s false
n equals s true
例2
Integer n1=127; //等价于 Integer n1=Integer.valueOf(128);
Integer s1=127; //等价于 Integer s1=Integer.valueOf(128);
System.out.println(" n1 == s1 "+(n1==s1));
System.out.println(" n1 equals s1 "+n1.equals(s1));
结果
n1 == s1 true
n1 equals s1 true
原因分析
object类的equals方向比较的地址
public boolean equals(Object obj)
{
return this == obj;
}
Integer类的equals重新object类,比较的是值
public boolean equals(Object obj)
{
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
所以例一和例二的equals都为true,但是比较地址时,127为true,128为false
因为Integer装箱时,会自动调用Integer.valueof方法。
public static Integer valueOf(int i)
{
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
所以如果ii >= IntegerCache.low && i <= IntegerCache.high 则会调用IntegerCache.cache
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) {
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;
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() {}
}
cache用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。
Integerl类第一次使用时,会初始化一个IntegerCache.cache的数组,数组里面存储-128 到 127之间的数字。
之后调用valueOf(i)方法时,如果i在-128 到 127之间,就会从IntegerCache.cache取出i对应的Integer对象;如果不在这个区间,就会返回new Integer(i)
注意事项
Integer s1=127;
Integer s2=new Integer(127);
System.out.println(" s1 == s2 "+(s1==s2));
System.out.println(" s1 equals s2 "+s1.equals(s2));
结果
s1 == s2 false
s1 equals s2 true
因为s1为IntegerCache.cache中的对象,s2为new 的新对象,所以二者地址不同