自动装箱与拆箱详解(JDK1.8)

什么是自动装箱与拆箱?

//自动装箱
Integer warp = 1;

//自动拆箱
int unWrap = warp;

实际上系统自动为我们执行了

Integer warp = Integer.valueOf(1);

int unWrap= warp .intValue();

以Integer为例

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

在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方法的实现是类似的。每次都返回不同的对象。


还有一种情况:Boolean

    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。原因如下

  1. 一个基础类型与包装类型进行+、-、*、/、==运算时会对包装类型进行拆箱,再和基本类型进行运算。
  2. 而equals()方法:
    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()方法不处理数据转型的关系,应尽量避免这样使用自动装箱与拆箱。

你可能感兴趣的:(自动装箱与拆箱详解(JDK1.8))