自动装箱和拆箱

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/peerless_hero/article/details/69818318

自动装箱和拆箱是什么

在Java中,数据类型可以分为两大类:Primitive Type(原始类型)和Reference Type(引用类型)。基本类型的数值不是对象,不能调用对象的toString()、hashCode()、getClass()、equals()等方法。

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int值转换成Integer对象,这个过程叫做装箱;反之将Integer对象转换成int值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。

原始类型对应的封装类如下表所示。

基本类型 大小 数值范围 默认值 包装类型
boolean true,false false Boolean
byte 8bit -2^7 ~ 2^7-1 0 Byte
char 16bit \u0000 ~ \uffff \u0000 Character
short 16bit -2^15 ~ 2^15-1 0 Short
int 32bit -2^31 ~ 2^31-1 0 Integer
long 64bit -2^63 ~ 2^63-1 0 Long
float 32bit IEEE 754 0.0f Float
double 64bit IEEE 754 0.0d Double
void Void

自动装箱和拆箱的使用场景

自动装箱时编译器调用valueOf将原始类型值转换成对象,而自动拆箱时编译器通过调用类似intValue(),doubleValue()等的方法将对象转换成原始类型值。

    /** 赋值时 **/
    ArrayList<Integer> intList = new ArrayList<Integer>();
    intList.add(1); //autoboxing -> primitive to object
    intList.add(2); //autoboxing

    ThreadLocal<Integer> intLocal = new ThreadLocal<Integer>();
    intLocal.set(3); //autoboxing

    int number = intList.get(0); // unboxing
    int local = intLocal.get(); // unboxing in Java

    /** 方法调用时 **/
    public static Integer show(Integer iParam){
        System.out.println("autoboxing example - method invocation i: " + iParam);
        return iParam;
    }

    //autoboxing and unboxing in method invocation
    show(4); //autoboxing
    int result = show(4); //unboxing because return type of method is Integer

自动装箱和拆箱的注意点

1.避免生成无用对象增加GC压力
下例在一个循环中进行自动装箱操作,它创建了多余的对象,影响了程序的性能。

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

“+”这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其内部变化如下:

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

由于声明的sum为Integer类型,在上面的循环中会创建将近4900个无用的Integer对象,这增加了垃圾回收的工作量,降低了程序的性能。因此在我们编程时需要正确地声明变量类型,避免因为自动装箱和拆箱引起的性能问题。

2.对象初始化
当我们进行一个原始数据值与一个对象的比较时,如果这个对象没有进行初始化或者对象为null,在自动拆箱过程中会抛出NullPointerException异常,代码如下:

    private static Integer count;

    // NullPointerException on unboxing
    if(count <= 0){
        System.out.println("Count is not started yet");
    }

3.对象缓存
Java默认会对-128到127的Byte、Short、Integer和Long对象进行缓存,当创建的对象在这个数值范围则返回已缓存的对象,否则创建新的对象。Character缓存的范围是0~127,而Float和Double没有自动装箱池。这种设计了享元设计模式,详见享元模式
然而,我们可以通过getAndRemoveCacheProperties方法来获取或移除JDK对Integer设置的缓存属性,同时可以通过调整虚拟机选项-XX:AutoBoxCacheMax来调整“自动装箱池”的大小 。

4.对象相等比较

    Integer integer1 = 100;  
    Integer integer2 = 100;  
    System.out.println("integer1==integer2: " + (integer1 == integer2));// true  自动装箱的两个缓存中的 Integer对象的引用比较  
    System.out.println("integer1.equals(integer2): " + (integer1.equals(integer2)));// true  
    System.out.println("integer1.compare(integer2): " + integer1.compareTo(integer2));// 0      
    Integer integer3 = 200;  
    Integer integer4 = 200;  
    System.out.println("integer3==integer4: " + (integer3 == integer4));// false 自动装箱的两个new Integer的引用比较  
    System.out.println("integer3>integer4: " + (integer3 > integer4)); // false 将两个对象拆箱,再比较大小  
    System.out.println("integer3.equals(integer4): " + (integer3.equals(integer4)));// true  
    System.out.println("integer3.compare(integer4): " + integer3.compareTo(integer4));// 0     
    Integer integer5 = new Integer(100);  
    Integer integer6 = new Integer(100);  
    System.out.println("integer5==integer6: " + (integer5 == integer6)); // false 两个不同的Integer对象引用的比较  
    System.out.println("integer5.equals(integer6): " + (integer5.equals(integer6)));// true  
    System.out.println("integer5.compare(integer6): " + integer5.compareTo(integer6));// 0      
    int int1 = 100;  
    System.out.println("integer1==int1: " + (integer1 == int1));// true  Integer缓存对象拆箱后与int比较  
    System.out.println("integer1.equals(int1): " + (integer1.equals(int1)));// true  
    System.out.println("integer1.compare(int1): " + integer1.compareTo(int1));// 0        
    int int2 = 200;  
    System.out.println("integer3==int2: " + (integer3 == int2));// true  Integer对象拆箱后与int比较  
    System.out.println("integer3.equals(int2): " + (integer3.equals(int2)));// true  
    System.out.println("integer3.compare(int2): " + integer3.compareTo(int2));// 0   
展开阅读全文

没有更多推荐了,返回首页