1拆箱和装箱的由来

上一篇博客中提到,java中既有基础数据类型,也有基础数据类型的包装类。其实,无论使用哪种,都可以顺利地建立变量。但是使用基础数据类型效率较高(java中的常量池),如果使用包装类可以使我们创建的变量非常强大,具有很多方法和功能。所谓的装箱和拆箱,也是由这个概念引出的。即,由基础数据类型变成包装类型,称为装箱;反之为拆箱。

举个简单的例子来帮助我们理解。

Int data1 = 10;
Integer data2 = new integer(data1);

通过这样的代码,我们成功将变量data1变成了类类型。

2自动拆箱和装箱

除了使用new创建基本数据类型打包器以外,从j2se5.0之后提供了自动装箱(autoboxing)功能,可以这样打包基本类型。

Integer wrapper =10;

与上面的例子相比,简洁了不少。这其实是虚拟机自动帮我们做了一些事情。Jdk自动将上面的代码展开为

Integer wrapper = integer.valueOf(10);

3陷阱

相对于手动装箱来说,自动装箱让我们写的程序变得非常简洁。为什么会简洁呢,因为虚拟机帮我们做了一些操作,隐藏了一些细节,从而让工作变得简洁。这本是好事,但在无形中设置了一些陷阱。

陷阱1:

Integer i = null;
In j = i;

分析:

这段代码在编译期可以通过,但是在执行期间却是有问题的。编译程序会自动将其展开为

Integer a= null; int I =a.intValue(); 这段代码中a是一个引用,被创建在栈中。但是系统并没有标明其具体指向的对象。所以a是不可能拥有任何方法的。因此,当后面打算强行使用的时候自然会出错的。

陷阱2

Integer i1 =100;
Integer i2=100;
If ( i1 == i2)
{system.out.println(“相同”)}

结果是相同。但是我们如果把100改成200会怎么呢。

Integer i1 =200;
Integer i2=200;
If ( i1 == i2)
{system.out.println(“相同”)}
Else
{system.out.println(“不相同”)}

结果却是不相同。这到底是为什么呢。

让我们追随大神的脚步,查看jdk文件中的src.zip中的java/lang

看看valueof()是怎么写的

public static Integer valueOf(int i) {
        assertIntegerCache.high >= 127;
        if (i >=IntegerCache.low && i <= IntegerCache.high)
            returnIntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

因为是菜鸟,所以没怎么看懂。大概意思好像是判断传入的int是否在InterCache.low与InterCache.high之间。如果在那么直接返回已经创建好的integer对象。如果不在这两者之间那么就会新创建一个inter个对象。所以,i1与i2就不相同了。