自动装箱、拆箱了解多少?

简介: Java 为我们提供了 8 种基本数据类型,为什么还需要提供各自的包装类型呢?您可能会觉得这个问题问的很奇怪,但是我觉得还是值的思考的。

写在前面

Java 为我们提供了 8 种基本数据类型,为什么还需要提供各自的包装类型呢?您可能会觉得这个问题问的很奇怪,但是我觉得还是值的思考的。

因为 Java 是一门面向对象的语言,基本数据类型并不具备对象的性质。而包装类型则是在基本类型的基础上,添加了属性和方法,从而成为了对象。试想,一个 int 类型怎么添加到 List 集合中?

如何理解Java中的自动拆箱和自动装箱?

自动拆箱?自动装箱?什么鬼,听都没听过啊,这...这..知识盲区...

回到家后赶紧查资料,我透,这不就是问基本类型跟封装类型吗,面试官整啥名词呢...

别问结果,问就是没过。

自动装箱、拆箱

定义: 基本数据类型和包装类之间可以自动地相互转换

理解: 装箱就是自动将基本数据类型转换为封装类型,拆箱就是自动将封装类型转换为基本数据类型。

我们来看个例子:

Integer number = 10; // 自动装箱
int count = number; // 自动拆箱
复制代码

我们知道,Java 中提供了四大类基本数据类型,分别是:整数、浮点数、字符型和布尔型,其中:

  • 整数包含:byte、int、short、long
  • 浮点数包含:float、double
  • 字符类型:char
  • 布尔类型:boolean

基本数据类型相信大家一定很熟悉了吧,来来来,说说他们的取值范围~

数据类型 取值范围
byte -128 ~ 127
short -32786 ~ 32767
int -4294967296 ~ 4294967295
long -264 ~ 264 -1
float 3.4e-038 ~ 3.4e+038
dubbo 1.7e-308 ~ 1.7e+308
char \u0000 ~ \uffff
boolean true 、false

日常开发中,靠这些基本数据类型几乎能够满足我们的需求,但是基本类型终究不是对象,往重了说不满足面向对象的开发思想,往轻了说就是使用不方便。怎么讲?例如做一些数据类型转换,获取 int 数据类型的取值范围等等。

我们知道,类的优点在于它可以定义成员变量、成员方法,提供丰富便利的功能,因此 Java 在 JDK1.0 的时候就设计了基本数据类型的包装类,而在 JDK1.5 中引入了新特性:自动装箱和拆箱。

我们来看一下基本类型跟封装类型之间的对应关系:

数据类型 封装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

何时会发生拆箱、装箱?

自动装箱和拆箱在 Java 中很常见,比如我们有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么 Java 会自动将这个原始类型值转换成与之对应的对象。最经典的一个场景就是当我们向 ArrayList 这样的容器中增加原始类型数据时或者是创建一个参数化的类,比如下面的 ThreadLocal。

ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1); // 装箱
intList.add(2); // 装箱
ThreadLocal<Integer> intLocal = new ThreadLocal<Integer>();
intLocal.set(4); // 装箱
int number = intList.get(0); // 拆箱
int local = intLocal.get(); // 拆箱
复制代码

上面的示例我们介绍了自动装箱和拆箱以及它们何时发生,我们知道了自动装箱主要发生在两种情况,一种是赋值时,另一种是在方法调用的时候。

赋值时

这是最常见的一种情况,在 Java 1.5 以前我们需要手动地进行转换才行,而现在所有的转换都是由编译器来完成。

// before autoboxing
Integer iObject = Integer.valueOf(3);
int iPrimitive = iObject.intValue()
//after java5
Integer iObject = 3; // autobxing - primitive to wrapper conversion
int iPrimitive = iObject; // unboxing - object to primitive conversion
复制代码

方法调用时

这是另一个常用的情况,当我们在方法调用时,我们可以传入原始数据值或者对象,同样编译器会帮我们进行转换。

public static Integer show(Integer iParam){
   System.out.println("autoboxing example - method invocation i: " + iParam);
   return iParam;
}
// autoboxing and unboxing in method invocation
show(3); // autoboxing
int result = show(3); // unboxing because return type of method is Integer
复制代码

show() 方法接受 Integer 对象作为参数,当调用 show(3) 时,会将 int 值转换成对应的 Integer 对象,这就是所谓的自动装箱,show() 方法返回 Integer 对象,而 int result = show(3); 中 result 为 int 类型,所以这时候发生自动拆箱操作,将 show() 方法返回的 Integer 对象转换成 int 值。

自动装拆箱的弊端

自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

Integer sum = 0;
for(int i=1000; i<5000; i++){
   sum += i;
}
复制代码

上面的代码 sum += i 可以看成 sum = sum + i,但是 + 这个操作符不适用于 Integer 对象,首先 sum 进行自动拆箱操作,然后进行数值相加操作,最后发生自动装箱操作转换成 Integer 对象。其内部变化如下:

int result = sum.intValue() + i;
Integer sum = new Integer(result);
复制代码

由于我们这里声明的 sum 为 Integer 类型,在上面的循环中会创建将近 4000 个无用的 Integer 对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。

总结

因为自动装箱会隐式地创建对象,像前面提到的那样,如果在一个循环体中,会创建无用的中间对象,这样会增加 GC 压力,降低程序的性能。所以在写循环时一定要注意,避免引入不必要的自动装箱操作。

总的来说,自动装箱和拆箱着实为开发者带来了很大的方便,但是在使用时也是需要格外留意,避免引起出现文章提到的问题。

相关文章
|
7月前
|
JSON 安全 Serverless
MCP Server On FC之旅2: 从0到1-MCP Server市场构建与存量OpenAPI转MCP Server
本文介绍了将社区主流STDIO MCP Server一键转为企业内可插拔Remote MCP Server的方法,以及存量API智能化重生的解决方案。通过FunctionAI平台模板实现STDIO MCP Server到SSE MCP Server的快速部署,并可通过“npx”或“uvx”命令调试。同时,文章还探讨了如何将OpenAPI规范数据转化为MCP Server实例,支持API Key、HTTP Basic和OAuth 2.0三种鉴权配置。该方案联合阿里云百练、魔搭社区等平台,提供低成本、高效率的企业级MCP Server服务化路径,助力AI应用生态繁荣。
1112 40
|
存储 监控 安全
前端框架的数据驱动方式如何保证数据的安全性?
总之,前端框架的数据驱动方式需要综合运用多种手段来保证数据的安全性。从传输、存储、访问控制到防范攻击等各个方面进行全面考虑和实施,以确保用户数据的安全可靠。同时,不断加强安全管理和技术创新,以应对不断变化的安全挑战。
450 60
|
8月前
|
安全 物联网 定位技术
贴身守护还是隐私威胁?可穿戴设备的安全隐忧
贴身守护还是隐私威胁?可穿戴设备的安全隐忧
233 15
|
前端开发 JavaScript 安全
前端JS实现密码校验键盘横竖、26字母、相同字母、相同数字、密码包含用户名、数字 字母不能连续 不能相同三个、不能横向 竖向 连续三个 包含字符、不能有中文符号
该 JavaScript 代码实现了一个严格的密码校验功能,确保密码满足多种安全要求,包括长度、字符类型、不包含中文及特殊字符、不与用户名相似等。通过多个辅助函数,如 `validateFormat` 检查密码格式,`isHasChinaCharFun` 检测中文符号,`getCharAll` 生成键盘组合,以及 `checkPasswordFun` 综合验证密码的有效性和安全性。此工具对于提高用户账户的安全性非常有用。
648 0
|
Ubuntu 网络协议 Linux
Linux下快速搭建七日杀官方私人服务器教程
本文提供了一份详尽的《七日杀》服务器搭建指南,专为Linux系统设计。教程分为九大部分,涵盖从前期准备到服务器维护的全过程。主要内容包括:选择具备公网IP的云服务器、安装Ubuntu 20 X64系统、下载SteamCMD等必备软件;详细指导如何配置服务器、设置防火墙及端口规则、启动与关闭服务器;此外还提供了服务器管理、环境配置(如设置swap分区)等实用技巧。适合有一定Linux基础的玩家参考实践。
|
存储 编解码
【头歌·计组·自己动手画CPU】一、计算机数据表示(讲解版) 【计算机硬件系统设计】
【头歌·计组·自己动手画CPU】一、计算机数据表示(讲解版) 【计算机硬件系统设计】
689 1
|
小程序
微信小程序实现点击复制(wx.setClipboardData)
微信小程序实现点击复制(wx.setClipboardData)
530 0
|
机器学习/深度学习 算法 数据挖掘
【机器学习】为什么K-means算法使用欧式距离度量?
【5月更文挑战第11天】【机器学习】为什么K-means算法使用欧式距离度量?
|
算法 测试技术 开发工具
[软件工程导论(第六版)]第1章 软件工程学概述(复习笔记)
[软件工程导论(第六版)]第1章 软件工程学概述(复习笔记)
|
Java 数据库连接 mybatis
Mybatis源码细节探究:sqlSessionFactory.openSession()这个方法到底发生了什么?
Mybatis源码细节探究:sqlSessionFactory.openSession()这个方法到底发生了什么?