Java学习记录--自动拆箱与装箱

先提问题

  1. 什么是自动拆箱与装箱?
  2. 什么情况下会自动拆箱与装箱?
  3. 对性能的影响?
  4. 使用建议

什么是自动拆箱与装箱?

自动拆箱与装箱是Java5引入的新特性,目的是解决基本类型与包装类型之间切换的麻烦. 装箱

Integer num = 1;

编译之后的代码如下,此时Integer.valueOf()把基本类型转换为包装类型叫装箱.

Integer num = Integer.valueOf((int)1);

拆箱

// 装箱
Integer num = 1;
Integer num2 = 2;
// 先拆再装
Integer num3 = num + num2;

编译之后代码,调用num.intValue()的过程叫做拆箱.对于+操作符,其只支持基本类型,因此必然会先拆箱,最后结果又是Integer包装类型,因此赋值时发生了装箱.

Integer num = Integer.valueOf((int)1);
Integer num2 = Integer.valueOf((int)2);
Integer num3 = Integer.valueOf((int)(num.intValue() + num2.intValue()));

简单来说,基本类型与包装类型在某些操作符的作用下,发生包装类型调用valueOf()方法的过程叫做装箱,基本类型调用xxValue()的过程叫做拆箱.

什么情况下会自动拆箱与装箱?

拆箱

  1. 只支持基本类型的操作符,如+-*/
  2. 包装类型与基本类型共同进行多元操作.例如包装类型->基本类型赋值double num7 = new Double(1).

装箱

  1. 包装类型与基本类型共同进行多元操作.例如基本类型->包装类型赋值double double1 =10D

举例:

 // 正常赋值
 double double1 =10D;
 //装箱 基本类型 -> 包装类型  
 Double double2 =10D;
// 装箱 基本类型 -> 包装类型  
 Double double3 =10D;
 // double2拆箱  +号只支持基本类型
 double double4 = double1 + double2;
 // double2,double3拆箱,double5装箱  +号只支持基本类型,基本类型 -> 包装类型 
 Double double5 = (double2 + double3);

==的特殊性 ==操作符既支持基本类型又支持包装类型(引用类型),那么某些地方必然会有歧义,这类操作符有一个原则,当有基本类型时以基本类型为主.

double double1 =10D;
Double double2 =10D;
Double double3 =10D;
// double2拆箱,因此比较值
System.out.println(double1 == double2); //true
// 包装类比较,直接比较引用地址.
System.out.println(double2 == double3); //false

对性能的影响?

装箱与拆箱本质是创建对象(valueOf)与调用对象方法(xxValue),没有多小性能消耗.但是在循环中也可能成为拖慢系统的最后一根稻草.如下面代码再一次循环中会有两次拆箱,一次装箱的消耗,不考虑缓存的影响循环多少次就创建了多少个Integer对象,虽然执行仍然会很快,但是把cpu浪费在这种地方有些得不偿失了.

Integer num = 1;
// num先拆箱再比较
while (num < 100000) {
    // num先拆箱,然后执行++再装箱
  num++;
  // do something
}

使用建议

关于使用需要了解两方的优势: 对于基本类型: 优点速度快,内存占用低,缺点无法表示不存在情况 对于包装类型: 优点有null值代表不存在情况,缺点速度慢,内存占用高(相对于基本类型) 那么基本类型与包装类型就是互补的存在了,具体使用哪个根据你是否有值不存在的这一情况表示决定. 日常开发建议遵循阿里Java开发手册:

  1. (强制)所有POJO类属性必须使用包装类型
  2. (强制)RPC方法返回值和参数必须包装类型
  3. (推荐)所有局部变量使用基本类型

其他

最后推荐下一款反编译插件,可以直接看到去糖后的代码 https://github.com/mrdear/asm-bytecode-intellij

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏chenjx85的技术专栏

leetcode-485-Max Consecutive Ones

1535
来自专栏技术小黑屋

Java中的字符串常量池

Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String...

1562
来自专栏博客园

.NET面试题解析(01)-值类型与引用类型

3. delegate是引用类型还是值类型?enum、int[]和string呢?

952
来自专栏阮一峰的网络日志

图解 Monad

函数式编程有一个重要概念,叫做Monad。 ? 网上有很多解释(这里和这里),但都很抽象,不容易看懂。我尝试了好多次,还是不明白Monad到底是什么。 ? 昨天...

3334
来自专栏Java进阶之路

Java8新特性实践

1700
来自专栏小狼的世界

Python3.6学习笔记(三)

面向对象编程 Object Oriented Programming 简称 OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作...

832
来自专栏不想当开发的产品不是好测试

java中int和Integer对比的一些坑

Integer是int的包装类,int的默认值是0,而Integer的默认值是null(jdk1.5的新特性 自动装箱和拆箱,Integer.valueOf()...

3571
来自专栏鸿的学习笔记

Python和Scala的类和对象(一)

前面的文章我们更多的是关注于函数,现在开始进入面向对象的世界了。函数是一种对过程的抽象,它提供了单一的入口和出口,封装了一系列的逻辑处理,而类和对象更像是对物体...

1031
来自专栏非著名程序员

Android开发工具之ParcelUtils和SerializeUtils

今天我们来讲的这两个工具类是在Activity之间跳转时常常要传递的和对象序列化什么有关的。那么接下来,我们来看看吧! SerializeUtils 包含一...

1816
来自专栏从零开始学 Web 前端

从零开始学 Web 之 ES6(六)ES6基础语法四

在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!

914

扫码关注云+社区

领取腾讯云代金券