Java装箱与拆箱

1. 基本概念

装箱:自动将基本数据类型转化为引用类型包装起来
拆箱:将包装类型转换为基本数据类型;

//自动装箱
Integer total = 99; 
//自动拆箱
int totalprim = total;

2. 过程

Integer total = 99;
执行上面那句代码的时候,系统为我们执行了:
Integer total = Integer.valueOf(99);

int totalprim = total;
执行上面那句代码的时候,系统为我们执行了:
int totalprim = total.intValue();
valueOf函数

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

首先它会判断i的大小,如果i小于等于-128(static final int low = -128;)或者大于等于128,就创建一个Integer对象,否则执行IntegerCache.cache[i + (-IntegerCache.low)];
Cache的计算

static final Integer cache[];
cache = new Integer[(high - low) + 1]; //low=-127, high=127 长度为256
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);//从-127到128

Cache是一个静态的数组对象,值从-127到128,共256个值
也就是说,
在i >= 128 || i < -128 下,会创建一个Integer对象,new Integer(i)
在i < 128 && i >= -128, 会根据i的值返回已经创建好的指定的对象(cache[i + 127])
例子

public class Main {
    public static void main(String[] args) {

        Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;

        System.out.println(i1==i2);  //true
        System.out.println(i3==i4);  //false
    }
}

再次解释,i1和i2等于100,那么就返回已经创建好的数组对象的值(cache[i + 127]),而i3和i4会分别创建一个对象,所以他们不相同。
又一个例子

public class Main {
    public static void main(String[] args) {

        Double i1 = 100.0;
        Double i2 = 100.0;
        Double i3 = 200.0;
        Double i4 = 200.0;

        System.out.println(i1==i2); //false
        System.out.println(i3==i4); //false
    }
}

解释:
因为对于Integer,在(-128,128]之间只有固定的256个值,所以为了避免多次创建对象,我们事先就创建好一个大小为256的Integer数组,所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。
但是对于Double类型来说,我们就不能这样做,因为它在这个范围内个数是无限的。

public static Double valueOf(String s) throws NumberFormatException {
        return new Double(parseDouble(s));
    }

总结:
Integer派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double派别:Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。

Boolean类型

例子:

public class Main {
    public static void main(String[] args) {

        Boolean i1 = false;
        Boolean i2 = false;
        Boolean i3 = true;
        Boolean i4 = true;

        System.out.println(i1==i2);//true
        System.out.println(i3==i4);//true
    }
}

可以看到返回的都是true,也就是它们执行valueOf返回的都是相同的对象。

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

可以看到它并没有创建对象,因为在内部已经提前创建好两个对象,因为它只有两种情况,这样也是为了避免重复创建太多的对象。


    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code true}.
     */
    public static final Boolean TRUE = new Boolean(true);

    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code false}.
     */
    public static final Boolean FALSE = new Boolean(false);

自动装箱和拆箱操作

Integer num1 = 400;  
int num2 = 400;  
System.out.println(num1 == num2); //true

说明num1 == num2进行了拆箱操作

Integer num1 = 100;  
int num2 = 100;  
System.out.println(num1.equals(num2));  //true

equal比较的是内容本身,并且我们也可以看到equal的参数是一个Object对象,我们传入的是一个int类型,所以首先会进行装箱,然后比较,之所以返回true,是由于它比较的是对象里面的value值.
equals源码:

@Override
public boolean equals(Object o) {
     return (o instanceof Integer) && (((Integer) o).value == value);
 }

例子

Integer num1 = 100;  
int num2 = 100;  
Long num3 = 200l;  
System.out.println(num1 + num2);  //200
System.out.println(num3 == (num1 + num2));  //true
System.out.println(num3.equals(num1 + num2));  //fals

解释:
1、当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算
2. num3.equals(num1 + num2)为ture的条件是:
类型相同,内容相同
重点:
当 “==”运算符的两个操作数都是包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)

参考:详解Java的自动装箱与拆箱(Autoboxing and unboxing)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值