自动装箱&自动拆箱

2019-02-16  本文已影响1人  竹鼠不要中暑

自动装箱就是自动将基本数据类型转换为包装器类型;自动拆箱就是自动将包装器类型转换为基本数据类型。
需要装箱拆箱的类型有:


包装类型

对于基本数据类型,Java提供了对应的包裹(wrap)类型。这些包裹类型将一个基本数据类型的数据转换成对象的形式,从而使得它们可以像对象一样参与运算和传递。
上图中的蓝色方框即为java八种基本数据类型所对应的包装类型。
在第一周的打印基本类型的最大值最小值一题中我就用到了包装类型:


向像Character有一些好用的方法,如Character.isDigit, Character.toLowerCase等;
练习自动类型转换,其实自动装箱和拆箱也很好理解,因为它转换的类型是包装类,将一个基本数据转换为了类,所以称为装箱。
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1); //自动装箱 int to Integer
intList.add(2); //自动装箱 int to Integer

int number = intList.get(0); // 自动拆箱 Integer to int, numer = 1

自动装箱拆箱主要发生在赋值时和方法调用时。

自动装箱/拆箱的缺点

自动装箱/拆箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

Integer sum = 0;
 for(int i=1000; i<5000; i++){
   sum+=i;
}

在进行没一次的sum+=i运算时,都要先拆箱,再相加,然后又装箱,相当于:

sum = sum.intValue() + i;
Integer sum = new Integer(sum);

注意的事项

对象相等比较

这是一个比较容易出错的地方,”==“可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==“,而应该使用对象对应的equals方法。看下例:

public class AutoboxingTest {

    public static void main(String args[]) {

        // Example 1: == comparison pure primitive – no autoboxing
        int i1 = 1;
        int i2 = 1;
        System.out.println("i1==i2 : " + (i1 == i2)); // true

        // Example 2: equality operator mixing object and primitive
        Integer num1 = 1; // autoboxing
        int num2 = 1;
        System.out.println("num1 == num2 : " + (num1 == num2)); // true

        // Example 3: special case - arises due to autoboxing in Java
        Integer obj1 = 1; // autoboxing will call Integer.valueOf()
        Integer obj2 = 1; // same call to Integer.valueOf() will return same
                            // cached Object

        System.out.println("obj1 == obj2 : " + (obj1 == obj2)); // true

        // Example 4: equality operator - pure object comparison
        Integer one = new Integer(1); // no autoboxing
        Integer anotherOne = new Integer(1);
        System.out.println("one == anotherOne : " + (one == anotherOne)); // false

    }

}

例3和例4的结果之所以不同,我的结果是例3中声明obj1和obj2 都为1,这个1是存在内存栈的一个引用变量,指向内存堆中为1的Integer对象,这个1就好像一个指针,指向内存堆中同一个Integer的地址,因此例3结果为true;而例4使用关键字new声明,声明的oneanotherOne指向内存堆中两个不同的Integer对象,地址不同,因此用==比较是为false.

上一篇下一篇

猜你喜欢

热点阅读