java 自动拆箱_Java中的自动装箱拆箱

Java中的自动装箱拆箱

一、自动装箱与自动拆箱

自动装箱就是将基本数据类型转换为包装类类型,自动拆箱就是将包装类类型转换为基本数据类型。

1 //自动装箱

2 Integer total = 90;3

4 //自动拆箱

5 int totalprim = total;

以 整数型 Integer 为例 ,从上面代码分析:装箱与拆箱的过程

(一)、自动装箱

total声明的是包装类型Integer,数值90是数据常量,当执行Integer total = 90时,系统为我们执行了Integer total = Integer.valueOf(99);

首先看一下:valueOf(int i)方法源码:IntegerCache.low = -128,IntegerCache.high = 127,IntegerCache.cache[ ]是Integer类型的数组

e006183e05bc9c577869d1c08ed7da9f.png

首先判断 i 的大小:如果 i =< -128或者i  >= 127,否则就创建一个Integer对象,否则返回 IntegerCache.cache[i + 128];

然后再看Integer的构造方法:

623b5459f5b2290bac6302e0eb626301.png

084229b49e262985ae9ca6db3a67086f.png

Integer定义了 一个  private final int value; 当创建一个Integer对象,就会给这个变量初始化。第二个构造方法传入的是一个String变量,它会先把它转换成一个int值,然后进行初始化。

IntegerCache.cache[ ]数组是 Integer 的内部类,定义了 static final Integer cache[]; 它是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象。

所以我们这里可以总结一点:装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。

(二)、自动拆箱

totalprim 声明的基本数据类型 int,total 是 包装类型 Integer ,当执行 int totalprim = total时,系统会自动调用 intValue()方法。首先看一下intValue方法:

7ac19074e297871c954b3b6ebf26d83c.png

intValue方法较简单,直接返回 value 的值。

二、相关问题

自动装箱时,分别有两种情况:

1、i >= 128 || i < -128 =====> new Integer(i)

2、i < 128 && i >= -128 =====> IntegerCache.cache[i + 128]

IntegerCache.cache[ ] 是Integer 的内部类中定义的数组对象,本来已经创建好了,也就是说在i >= 128 || i < -128是会创建不同的对象,在i < 128 && i >= -128会根据 i 的值返回已经创建好的指定的对象。

举个例子:

91e56df1d912159e5a5d626bfd8c4f1a.png

通过执行上面的代码,分别输出了 true 和 false,数值一样,结果却不同,这是为什么呢?

①、i1 和 i1 都赋值为100,属于自动装箱的第二种情况,所以返回的是IntegerCache.cache[ ]数组中的对象,由于引用的是同一个 Integer 对象,所以他们的地址值是相等的,即他们是相等的。

②、i3 和 i4 都赋值为200,属于自动装箱的第一种情况,valueOf 方法会生成新的对象并返回,由于是分别引用的对象,两个对象的地址值不同,所以 “==” 判断时,他们是不相等的。

三、浮点型和布尔型的装箱拆箱

(一)、浮点型

9ae734815e22dbac817960a0fd9d4182.png

数值相同,结果和 Integer 不同 ,和 Integer 类似,当调用 Double d1 = 100.0 时,系统会调用valueOf(double d),首先看一下源码 :

f0a5ab0a185d6e80d599ada7a66b4a15.png

每次调用 valueOf 方法时,都会新生成一个 Double 对象 ,所以他们引用对象的地址值都不一样,因为 Integer 内部维护了一个IntegerCache.cache[ ] ,而IntegerCache.cache[ ]对象在整数型中的长度是固定的,所以在满足范围时返回的是同一个引用对象;而浮点型数据范围是无限大的,定义数组不太现实,所以直接生成新的对象。

(二)、布尔型

d23939373ec216dc622538fe8531c7b1.png

可以看到返回的都是true,也就是它们执行valueOf返回的都是相同的对象。和上面类似,当调用 Boolean b1 = false 时,系统会调用valueOf(boolean b),首先看一下源码 :

f0aaf64c94a28680bc93fa22001343ea.png

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

(三)、小结

整数型派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。

浮点数型派别:Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。

四、基础数据类型与包装类进行 ==、+、-、*、/ 运算

(一)运算

当基本数据类型进行普通的运算时,直接进行运算。

当包装类进行运算时,会先将包装类拆箱成基本数据类型,然后进行运算。

(二)、equals与 “==” 比较

包装类型重写了 Object 的 equal 方法,equal 比较的是内容本身,并且我们也可以看到equal的参数是一个Object对象,我们传入的是一个int类型,所以首先会进行装箱,然后比较对象里面的value值。

“==”运算符的两个操作数如果都是包装类类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。

五、总结

装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。

equals(Object o) 因为原equals方法中的参数类型是封装类型,所传入的参数类型(a)是原始数据类型,所以会自动对其装箱,反之,会对其进行拆箱

当两种不同类型用==比较时,包装器类的需要拆箱, 当同种类型用==比较时,会自动拆箱或者装箱

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值