一、详解Java的自动装箱与拆箱(Autoboxing and unboxing)
https://www.cnblogs.com/wang-yaz/p/8516151.html
Integer total = 99; // 反编译后,实际代码:Integer total = Integer.valueOf(99);,自动装箱:.valueOf()
int totalprim = total; // int totalprim = total.intValue();,自动拆箱:.intValue()
Integer i = 100;
int j = 99;
Object k = i + j;// i3是Integer类型,因为有Object?
public static void main(String[] args) {
/*
public static Integer valueOf(int i) {
return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
}
private static final Integer[] SMALL_VALUES = new Integer[256]; SMALL_VALUES[0] = -128
*/
Integer i1 = 127; // 小于128,在提前创建的SMALL_VALUES中取用,所以是同一个对象
Integer i2 = 127;
Integer i3 = 128; // 无论如何,都new新的Integer
Integer i4 = 128;
System.out.println("i1 = i2:" + (i1 == i2)); // true
System.out.println("i3 = i4:" + (i3 == i4)); // false
Double d1 = 127.0; // Double中间有无数个数,无法先创建好数组供选择,只能每次都new Double()
Double d2 = 127.0;
Double d3 = 128.0;
Double d4 = 128.0;
System.out.println("d1 = d2:" + (d1 == d2)); // false
System.out.println("d3 = d4:" + (d3 == d4)); // false
Integer i5 = 100;
int i6 = 100;
Long l1 = 200L;
1、当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
2、对于l1.equals(i5 + i6)为false的原因很简单,我们还是根据代码实现来说明:
3、当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象;而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。
@Override
public boolean equals(Object o) {
return (o instanceof Long) && (((Long) o).value == value);
}
它必须满足两个条件才为true:
1、类型相同
2、内容相同
*/
System.out.println("i5 = i6:" + (i5 == i6)); //true
//先对l1拆箱,然后对i5、i6拆箱,进行运算比较
System.out.println("i5 + i6 = l1:" + (l1 == (i6 + i5))); //true
System.out.println("i5 + i6 equals l1:" + (l1.equals((i6 + i5)))); //false
}
- 总结:
1、需要知道什么时候会引发装箱和拆箱。
2、装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。
3、equals(Object o) 因为原equals方法中的参数类型是封装类型,所传入的参数类型是原始数据类型,所以会自动对其装箱,反之,会对其进行拆箱。
4、当两种不同类型用==比较时,包装器类的需要拆箱, 当同种类型用==比较时,会自动拆箱或者装箱。