什么是自动装箱与拆箱?
//自动装箱
Integer warp = 1;
//自动拆箱
int unWrap = warp;
实际上系统自动为我们执行了
Integer warp = Integer.valueOf(1);
int unWrap= warp .intValue();
Integer.valueOf(int i)方法:
public static Integer valueOf(int i) {
//low为-128,high值可能由属性决定,一般为127
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
即若i的值在-128~127之间则Integer会直接在缓存中取值,减少内存的消耗。所以在这个值范围内执行下列代码:
Integer a = 1;
Integer b = 1;
System.out.println(a==b);
打印出来的是true。
但如果 i < -128或 i > 127,则会直接新建一个Integer对象。倘若这时我们再执行下述代码:
Integer a = 128;
Integer b = 128;
System.out.println(a==b);
返回值就变成了false。
intValue()方法:
public int intValue() {
return value;
}
直接返回值。
在Double与Float中ValueOf方法与Integer中的又有不同。我们以Double为例:
public static Double valueOf(double d) {
return new Double(d);
}
我们可以看到在Double中是直接new一个对象出来的,所以如果我们执行下列代码:
Double g = 3.0;
Double h = 3.0;
System.out.println(g==h);
打印出来的结果为false。
查阅资料与相关博客后,我们可以分为两个类别:
Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
在Boolean中,它并没有创建新的对象,而是使用在内部提前创建好的两个对象。
所以执行下面代码:
Boolean c = true;
Boolean d = true;
Boolean e = false;
Boolean f = false;
System.out.println(c==d);
System.out.println(e==f);
返回结果都为true。
继续以最开始的代码为例:
Integer warp = 1;
int unWrap = warp;
System.out.println(warp == unWarp);
System.out.println(warp.equals(unWarp));
返回结果都为true。原因如下
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
可以看到参数为Object类型,我们传入的是int类型所以会先进行装箱,再比较对象里的value值。
但如果我们执行下面代码:
Integer warp = 300;
Long test = 200L;
Long test2 = 100L;
//true
System.out.println(warp == (test + test2));
//false
System.out.println(warp.equals(test + test2));
因为传入的类型不同,所以最后一个的结果返回false。
需要注意:
Integer warp = null;
int unWrap = warp;
这两行代码虽然在编译器中是合法的,但是运行的时候会抛出指针异常:Exception in thread "main" java.lang.NullPointerException
这是因为在第二行拆箱的时候,等于对null执行了intValue();
方法,所以会抛出空指针异常。
鉴于包装类的“==”运算在不遇到算术运算的情况下不会自动拆箱,以及它们的equals()方法不处理数据转型的关系,应尽量避免这样使用自动装箱与拆箱。