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

小伟刚毕业时面的第一家公司就被面试官给问住了,记忆尤深啊…

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

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

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

别问结果,问就是没过。

1、 什么是自动装箱,自动拆箱

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

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

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

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

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

数据类型取值范围
byte-128 ~ 127
short-32786 ~ 32767
int-4294967296 ~ 4294967295
long-264 ~ 264 -1
float3.4e-038 ~ 3.4e+038
double1.7e-308 ~ 1.7e+308
char\u0000 ~ \uffff
booleantrue 、false

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

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

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

数据类型封装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

2、 使用包装类型后的便捷

我们以上边提到的数据类型转换为例,看看使用包装类型后的便捷性。

小伟在数据库中存放商品库存用的是 varchar 类型来存储的,所以在代码中的实体与之对应的是 String,那么问题来了,既然是库存,那么势必就要用到加减乘除之类的运算,所以就需要先转换成 数值类型(int\long\float等)来运算,我们看一下通过包装类是如何快速转换的「int\long\float」:

public class Test {public static void main(String[] args) {// 数据库中的商品数量 numberString number = "666";// 借助封装了 Integer 转换为 intint intVal = Integer.valueOf(number);// 借助封装了 Float 转换为 floatfloat floatVal = Float.valueOf(number);// 借助封装了 Long 转换为 longlong longVal = Long.valueOf(number);// 依次输出三个值的内容System.out.println("int="+intVal);System.out.println("floatVal="+floatVal);System.out.println("longVal="+longVal);}
}

3、 落实自动装箱、拆箱

看完了包装类型的便捷性后,我们再来落实到自动装箱、自动拆箱上…

怎么就自动装箱,自动拆箱了呢?

上一段代码,看看哪是自动装箱跟自动拆箱:

// 自动装箱
1. Integer a = 100;
// 自动拆箱
2. int b = a;

自动装箱,相当于Java编译器替我们执行了 Integer.valueOf(XXX);

自动拆箱,相当于Java编译器替我们执行了Integer.intValue(XXX);

我们证实一下,首先通过 javac 编译得到 class 文件,接着反编译看看:

指令为:javap -c class文件名,得到下图所示:

看完编译器替我们做的,接下来我们再通过源码看看,首先是自动装箱 valueOf() 方法:

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

我们可以看到,首先是if方法, 对传入的int 数值进行判断,如果 i >= -128i <= 127 那么就会从IntegerCache缓存中获取指定数字的封装类,如果不存在则 new 出一个新的封装类,关于 IntegerCache ,其内部实现了一个Integer的静态常量数组,在类加载的时候,执行static静态块进行初始化-128~127之间的Integer对象,存放到cache数组中,cache属于常量,存放在java的方法区中,对方法区不太了解的小伙伴可以先留空,后面我会单独水一篇的~

额外补充一下:上边我们只看了Integer封装类的自动装箱方法,从方法中我们了解了在-128~127之间使用了缓存,那么是不是意味着别的封装类也是这样呢?其实不是的,首先Integer使用缓存原因是该区间会被经常使用到,且数量个数比较确定,就256个值,所以为了提高效率,防止每次自动装箱都创建一次对象实例,然后就你懂得~,而double、float浮点型是没有使用缓存的,因为小数点的原因,所以在这个区间范围内个数是比较泛的,即不适合缓存,没有意义。

我们通过一段代码看看这个缓存的效果吧:

public class Test2 {public static void main(String[] args) {Integer a = 100;Integer b = 100;Integer c = 200;Integer d = 200;System.out.println(a==b); // 打印trueSystem.out.println(a==b); // 打印false}
}

接着再来看自动拆箱 intValue() 方法:

private final int value;public int intValue() {return value;
}

这个方法就比较简单了,调用时直接返回了基本数据类型的 value 值。

至此我们看完了自动装箱、自动拆箱,以Integer为例我们知道了使用 valueOf() 方法实现装箱,使用 intValue() 方法实现拆箱,接下来我们再结合几行代码重新回顾一下:

1. Integer a = new Integer(100);
2. Integer b = 100;
3. b+=100;
  • 第一行代码:new 了一个 Integer 对象实例,将 int 类型的数据传入包装成了 Integer 类型。

  • 第二行代码:首先我们知道 100 是 int 类型的,但是等待复制的 b 是 Integer 类型,此时就用到了自动装箱,b = Integer.valueOf(100),将100包装成包装类了「通过反编译验证」

  • 第三行代码:用到了自动装箱+自动拆箱,b = b + 100 = Integer.intValye(b) + 100 此时计算结果得到的应该是 int 类型的 b,但是 b 又被限定了是 Integer 类型,所以就又要用到 Integet.valueOf() 自动装箱。

4、 上才艺

才艺一:如何理解Java中的自动拆箱和自动装箱?

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

才艺二:能说一下是通过哪些方法实现自动拆箱、装箱的吗?

答:以Integer为例,使用Integer.valueOf()方法实现装箱,使用Integer.intValue()方法实现拆箱。

推荐阅读:

跟小伟一起学习类加载机制

为什么有这么多领优惠劵的群?

单招计算机类哪个专业比较好

本文首发于博客园:https://www.cnblogs.com/niceyoo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/414002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[js] 实现多张图片合成一张的效果

[js] 实现多张图片合成一张的效果 原理是使用canvas画布。在页面加载前 mounted方法里&#xff1a;setTimeout(() > {this.changeimg();}, 1000);changeimg( )方法&#xff1a;changeimg(){var self this;var imgsrcArray [require(../../assets/image/income/background…

chrome浏览器中解决embed标签 loop=true 背景音乐无法循环的问题。

今天试了下在html网页中加入背景音乐并设置为循环播放。一开始用<embed>标签&#xff0c;设置loop"true", 但是结果发现在IE浏览器可以&#xff0c;但是在chrome浏览器却无法实现循环&#xff0c; 播放完一次自动停止了。代码如下&#xff1a; <embed src&q…

基于Docker的Redis集群简单搭建

环境&#xff1a;Docker ( Redis:5.0.5 * 3 ) 1、拉取镜像 docker pull redis:5.0.52、创建Redis容器 创建三个 redis 容器&#xff1a; redis-node1&#xff1a;6379redis-node2&#xff1a;6380redis-node3&#xff1a;6381 docker create --name redis-node1 -v /data…

[js] ajax如何接收后台传来的图片?

[js] ajax如何接收后台传来的图片&#xff1f; 1.设置responseType为 Blob&#xff0c;2.将Blob保存为文件个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

Python 全栈开发十 socket网络编程

一、客户端&#xff08;client&#xff09;服务端&#xff08;sever&#xff09;架构 在计算机中有很多常见的C/S架构&#xff0c;例如我们的浏览器是客户端、而百度网站和其他的网站就是服务端&#xff1b;视频软件是客户端&#xff0c;提供视频的腾讯、优酷、爱奇艺就是服务端…

[js] js源代码压缩都有哪些方法?它们的压缩原理分别是什么

[js] js源代码压缩都有哪些方法&#xff1f;它们的压缩原理分别是什么 方法 1.在线工具 2.webpack原理 1.删除注释 2.变量名方法名字符精减个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与…

基于Docker方式实现Elasticsearch集群

文本环境&#xff1a;Docker (Elasticsearch6.8.5 * 3) 1、拉取Elasticsearch docker pull elasticsearch6.8.52、创建es挂载目录 创建3个文件夹用于存放es挂载地址&#xff1a;es01、es02、es03 [rootCentOS7 ~]# mkdir /es-cluster [rootCentOS7 ~]# cd /es-cluster/ [ro…

[js] 不用 + eval Function 实现加法

[js] 不用 eval Function 实现加法 // 使用位运算符实现 function add (a, b) {if (a 0 || b 0) {return a || b;}while (b ! 0) {let i b;b (a & b) << 1;a a ^ i;}return a; };个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&…

基于Docker搭建Gitlab代码存储

关于Docker搭建Gitlab&#xff0c;在19年时就已经在博客发过文章了&#xff0c;今天重新回顾一下。 1、拉取镜像 docker pull gitlab/gitlab-ce默认拉取最新版本&#xff1a; 2、创建Gitlab配置 创建GitLab 的配置 (etc) 、 日志 (log) 、数据 (data) 放到容器之外&#xff…

Java Web开发技术教程入门-JavaBean组件与Servlet

补更&#xff1a;阅战阅勇第7/8/9Days笔记昨天我们了解了JDBC技术的一些日常操作&#xff0c;对于数据库而言&#xff0c;不仅仅的只有“增&#xff0c;删&#xff0c;改&#xff0c;查”。博主觉得最重要的是SQL语句的优化&#xff0c;一个“完美”的SQL语句可以大大减少程序的…

[js] 写一个 document.querySelector 的逆方法

[js] 写一个 document.querySelector 的逆方法 document.queryNode function(node){if(node.id){return # node.id;}if(node.className){return . node.id;}return node.nodeName; };个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但…

读书笔记--Android Gradle权威指南(上)

本篇文章已授权微信公众号 dasu_Android&#xff08;大苏&#xff09;独家发布 最近看了一本书《Android Gradle 权威指南》&#xff0c;对于 Gradle 理解又更深了&#xff0c;但不想过段时间就又忘光了&#xff0c;所以打算写一篇读书笔记&#xff0c;将书中一些我个人觉得蛮有…

[js] 如何判断对象是否属于某个类?

[js] 如何判断对象是否属于某个类&#xff1f; obj.proto class.prototype 可以递归去找obj instanceof class个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

基于Docker搭建私有镜像仓库

通常我们在docker中拉取的镜像都是在docker hub在线存储库中获取的&#xff0c;这个在线存储库里的docker镜像可以由任何用户发布和使用&#xff0c;显然这在某些场景下是不适用的&#xff0c;比如某些互金的隐私项目&#xff0c;或者是公司完全处于内网状态不能访问外网&#…

[js] 说说你对js沙箱的理解,它有什么应用场景?

[js] 说说你对js沙箱的理解&#xff0c;它有什么应用场景&#xff1f; 在微前端有用到js沙箱&#xff0c;例如qiankun框架&#xff0c;主应用的js运行和子任务的js运行不会相互影响&#xff0c;是使用es6的proxy来实现的个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后…

volatile理解了吗?

到这里大家感觉自己对volatile理解了吗&#xff1f; 如果理解了&#xff0c;大家考虑这么一个问题&#xff1a;ReentrantLock&#xff08;或者其它基于AQS实现的锁&#xff09;是如何保证代码段中变量&#xff08;变量主要是指共享变量&#xff0c;存在竞争问题的变量&…

Linux|CentOS下配置Maven环境

1、下载maven包 wget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz如果提示 wget: 未找到命令&#xff0c;请尝试如下指令安装 wget yum -y install wget2、解压下载的maven压缩吧 tar -xzvf apache-maven-3.3.…

[js] 纯函数和函数式编程有什么关系?

[js] 纯函数和函数式编程有什么关系&#xff1f; 函数式编程是一种编程思想&#xff0c;纯函数是这种思想的基本要实现函数式编程&#xff0c;我们所封装的方法应该是抽象的&#xff0c;应该是和外部状态无关系的&#xff0c;也就需要是纯函数的&#xff0c;这样才能保证抽象的…

PHP 超级全局变量

PHP 超级全局变量列表: $GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_ENV $_COOKIE $_SESSION 转载于:https://www.cnblogs.com/alexguoyihao/p/9086857.html

[js] 为什么要用纯函数?

[js] 为什么要用纯函数&#xff1f; 在此之前要先了解什么是纯函数&#xff0c;简单来说纯函数的定义有两个&#xff1a; 1.返回的结果只依赖于传入的参数。 2.执行过程中不产生副作用。 在这里就需要了解到什么是副作用 1.改变了外部变量或者对象属性 2.触发任何外部进程 3.发…