自动拆装箱

基本数据类型有什么好处:

在java语言中,new一个对象存储在堆里,通过栈中的引用来使用这些对象,所以对象本身来说是比较耗资源的,对于经常使用到的类型,如int等,若我们每次使用这种变量时都需要new个java对象会显得很笨重,因此提供了基础数据类型,无需使用new创建,他们不会在堆上创建,而是直接在栈内存中存储,会更加高效。

关于自动拆装箱_System


但由于java是一个面向对象的语言,java的基本数据类型不面向对象,这在实际使用中会有不足(比如集合类,我们无法将int,double等类型放进去,因为集合容器要求元素是Object类型),因此设计类时为每一个基本数据类型设计一个对应的类来进行代表,因此八个基本数据类对应的类统称为包装类。

包装类都位于java.lang包:

关于自动拆装箱_java_02


拆箱和装箱:

我们认为包装类是对基本类型的包装,所以把基本数据类型装换成包装类的过程就叫打包装,也就是装箱,反之就是拆箱。

javaSE5之前需要进行装箱,如:

Integer i = new Integer(10);

自动拆装箱:

自动装箱: 就是将基本数据类型自动转换成对应的包装类。

自动拆箱:就是将包装类自动转换成对应的基本数据类型。

Integer integer = 10;  //自动装箱
int b = integer; //自动拆箱

Integer i=10 可以替代 Integer i = new Integer(10);,因为java帮我们提供自动装箱功能,无需开发者手动取new一个Integer对象。
实现原理:
自动装箱都是通过包装类valueOf()方法实现的,自动拆箱都是通过包装类对象的xxxValue()实现的。

public static  void main(String[]args){
Integer integer=Integer.valueOf(10);
int i=integer.intValue();
}

哪些场景会用到自动拆装箱:
1,将基本数据类型放入集合类(之前解释过)当我们把基本数据类型放入集合类中的时候,会进行自动装箱。
2,包装类型和基本类型的大小比较:包装类与基本数据类型进行比较运算,是先将包装类进行拆箱成基本数据类型,然后进行比较的。
代码反编译:

Integer a = 1;
System.out.println(a.intValue() == 1 ? "等于" : "不等于");
Boolean bool = false;
System.out.println(bool.booleanValue ? "真" : "假");

3,包装类型的运算:两个包装类之间的运算会自动拆箱成基本类型进行。

Integer i = 10;
Integer j = 20;

System.out.println(i+j);

反编译后:

Integer i = Integer.valueOf(10);
Integer j = Integer.valueOf(20);
System.out.println(i.intValue() + j.intValue());

4,三目运算符的使用:在 int k = flag ? i : j; 这一行,会发生自动拆箱,如果此时i的值为null就会导致空指针异常。

boolean flag = true;
Integer i = 0;
int j = 1;
int k = flag ? i : j;

反编译后:

boolean flag = true;
Integer i = Integer.valueOf(0);
int j = 1;
int k = flag ? i.intValue() : j;
System.out.println(k);

5,函数参数与返回值

自动拆装箱和缓存

public static void main(String... strings) {

Integer integer1 = 3;
Integer integer2 = 3;

if (integer1 == integer2)
System.out.println("integer1 == integer2");
else
System.out.println("integer1 != integer2");

Integer integer3 = 300;
Integer integer4 = 300;

if (integer3 == integer4)
System.out.println("integer3 == integer4");
else
System.out.println("integer3 != integer4");
}

在 Java 中,== 比较的是对象引用,而 equals 比较的是值。所以,在这个例子中,不同的对象有不同的引用,所以在进行比较的时候都将返回 false。奇怪的是,这里两个类似的 if 条件判断返回不同的布尔值。
结果:

integer1 == integer2
integer3 != integer4
这与Integer中的缓存机制有关,java5中,在Integer操作上引入一个新功能节省内存和提高性能,具体细节以后再说,只需要记住自动装箱时,如果数字在-128到127之间就会直接使用缓存中对象,而不是重新创建一个对象。
为什么非要选择范围-128到127呢?
因为这个范围最广泛使用,在程序中,第一次使用Integer时也会需要额外时间来初始化这个缓存。

自动拆装箱的问题:

大大节省开发人员精力,无需关心合适拆装,但需要注意不能再简单使用==,在-128到127之外的数字还是需要equals比较,如果包装类对象为null也会导致空指针异常,而且for循环中有大量拆装箱操作,会浪费很多资源。