自动装箱、拆箱。
他们是java语言中使用最多的语法糖。
从如下代码开始说起:
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Integer h = new Integer(1);
System.out.println(c == d);//true
System.out.println(e == f);//false
System.out.println(c == (a+b));//true
System.out.println(c.equals(a+b));//true
System.out.println(g == (a+b));//true
System.out.println(g.equals(a+b));//false
System.out.print(a == h); //false
System.out.println("=========================");
}
Integer a = 1;
会被自动装箱成如下
Integer a = Integer.valueOf(1);
再来看看valueOf的源码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
这段代码中使用到的静态常量如下:
static final int low = -128;
static final int high;
static final Integer cache[];
static {
int h = 127;
...
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;
}
1、如果定义了两个Integer类型的变量,他们的值在[-128,128)之间,那么他们会拿已经定义好的缓存中的对象,包装类型==比较的是对象的地址,所以如下返回时true。
System.out.println(c == d);//true
2、对于1中[-128,128)区间外的值,如示例中的321,就会重新创建新的对象,所以如下结果false。
System.out.println(e == f);//false
3、当封装类型和基本类型进行==、+、-、*、/这五种运算时,会将封装类型自动拆箱,所以如下结果true。
System.out.println(c == (a+b));//true
4、看下Integer的equals源码如下,比较两个变量的类型相同且值相同,则true。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
如下代码中a+b首先进行拆箱进行计算后,再通过c.equals(Object obj)方法,基本类型通过Object转成封装类型Integer。所以如下true。
System.out.println(c.equals(a+b));//true
5、g是封装类型,a+b是基本类型,封装类型和基本类型进行==时,会自动拆箱成基本类型进行比较,所以如下为true。
System.out.println(g == (a+b));//true
6、看下Long的equals源码如下,比较两个变量的类型相同且值相同,则true,否则返回false。
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
如下代码中a+b首先进行拆箱进行计算后,再通过g.equals(Object obj)方法,基本类型通过Object转成封装类型Integer。所以如下
System.out.println(g.equals(a+b));//false
7、new对象会创建新的对象,Integer a = 1;是直接从常量池的缓存中取对象。所以false。
System.out.print(a == h); //false
总结:
1、相同类型的==比较的话,如果时引用类型,注意比较两个值是否相等,相等的话是否从缓存中引用对象。
2、对于+、-、*、/、==做运算的时候,会进行自动拆箱。
3、equals对于封装类型比较期类型和值,基本类型会被自动装箱。
4、注意new对象和直接定义Integer封装类型的对象不同。