知方号

知方号

深入浅出Java拆箱与装箱:理解自动类型转换与包装类的关系

13.3 拆箱和装箱

“哥,听说 Java 的每个基本数据类型都对应了一个包装类型,比如说 int 的包装类型为 Integer,double 的包装类型为 Double,是这样吗?”从三妹这句话当中,能听得出来,她已经提前预习这块内容了。

“是的,三妹。”我接着三妹的问题回答说。

Java 是面向对象的编程语言,但为了提升程序的运行效率,所以 Java 搞出来了基本数据类型这套东西,比如说 int、double、boolean 等等。后面我会讲为什么。但是,基本数据类型又不能满足所有的应用场景,比如说,我们定义一个 int 类型的 ArrayList,你就只能用 List list = new ArrayList(); 这种方式来定义,不能用 List list = new ArrayList(); 这种方式来定义,因为泛型不支持基本数据类型。后面我也会讲为什么。

那既然存在基本数据类型,又存在包装类型,它们之间肯定存在一些使用上的差异,以及在某些场景下需要进行类型转换。这就是今天我们要讲的拆箱和装箱。

拆箱就是将包装类型对象转换为其对应的基本数据类型,而装箱则是将基本数据类型转换为相应的包装类型对象。

示例代码如下:

Integer chenmo = new Integer(10); // 装箱int wanger = chenmo.intValue(); // 拆箱包装类型和基本数据类型之间的区别

好,接下来我们先来介绍一下包装类型和基本数据类型之间的区别。

包装类型可以为 null,而基本数据类型不可以

别小看这一点区别,这使得包装类型可以应用于 POJO 中,而基本数据类型则不行。

POJO 是什么呢?

POJO 的英文全称是 Plain Ordinary Java Object,翻译一下就是,简单无规则的 Java 对象,只有字段以及对应的 setter 和 getter 方法。来看下面这段代码:

class Writer {private Integer age;private String name;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

这就是一个非常纯粹,非常典型的 POJO,在我们编写的 Java 应用程序中会经常用到。

“哥,你说的 POJO 是不是就是 JavaBean 啊?”三妹这时候追问道。

“是的,如果定义没那么严格的话,JavaBean 也是一种 POJO。”

和 POJO 类似的,还有:

数据传输对象 DTO(Data Transfer Object,泛指用于展示层与服务层之间的数据传输对象)视图对象 VO(View Object,把某个页面的数据封装起来)持久化对象 PO(Persistant Object,可以看成是与数据库中的表映射的 Java 对象)。

技术派实战项目当中就有大量 POJO,我截图大家感受下,工作后其实会经常碰到。

只不过,我们不再写 setter 和 getter 方法,而是使用 Lombok 来自动生成。也就是上图当中的 @Data 注解。

“那为什么 POJO 的字段必须要用包装类型呢?”三妹又追问道。

“《阿里巴巴 Java 开发手册》上有详细的说明,你看。”我打开 PDF,并翻到了对应的内容,指着屏幕念道。

数据库的查询结果可能是 null,如果使用基本数据类型的话,因为要自动拆箱,就会抛出 NullPointerException 的异常。

“什么是自动拆箱呢?”

“自动拆箱指的是,将包装类型转为基本数据类型,比如说把 Integer 对象转换成 int 值;对应的,把基本数据类型转为包装类型,则称为自动装箱。”

“哦。”

包装类型可用于泛型,而基本数据类型不可以

“那接下来,我们来看第二点不同。包装类型可用于泛型,而基本数据类型不可以,否则就会出现编译错误。”一边说着,我一边在 Intellij IDEA 中噼里啪啦地敲了起来。

“三妹,你瞧,编译器提示错误了。”

List list = new ArrayList(); // 提示 Syntax error, insert "Dimensions" to complete ReferenceTypeList list = new ArrayList();

“为什么呢?”三妹及时地问道。

“因为泛型在编译时会进行类型擦除,最后只保留原始类型,而原始类型只能是 Object 类及其子类——基本数据类型是个例外。”

这个我们在讲泛型的时候,也有详细讲过,你应该还记得吧?

“嗯,我记得。”

基本数据类型比包装类型更高效

“哥,你之前说到,Java 搞出来了基本数据类型这套东西,是为了提升程序的运行效率,为什么呢?”三妹又追问道。

那这里其实就是为了讲这个问题。

“好,接下来,我们来说第三点,基本数据类型比包装类型更高效。”我喝了一口布丁奶茶后继续说道。

“作为局部变量时,基本数据类型在栈中直接存储的具体数值,而包装类型则存储的是堆中的引用。”我一边说着,一边打开 draw.io 画起了图。

关于堆和栈的知识,我们会在讲 JVM 运行时数据区的时候详细讲解。

很显然,相比较于基本类型而言,包装类型需要占用

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。