Java 自动装箱和拆箱

装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型
Java的类型分为两部分,一个是基本类型(primitive),如int、double等八种基本数据类型;另一个是引用类型(reference type),如String、List等。而每一个基本类型又各自对应了一个引用类型,称为包装类型(或装箱类型,boxed primitive)
通过一个例子来理解,每个输出结果我都注释在上方了
在这里插入图片描述
如图上的代码,每一个都是包装类型Integer和Long
第一,二个输出涉及到JVM 常量池(Constant Pool Table)的知识
这里简要讲一讲常量池相关的知识。
常量池是运行时常量池(Runtime Constant Pool)一项,而运行时常量池是方法区的一部分,方法区是所有线程共享的数据区。
常量池用于存放编译期生成的各种字面量和符号引用 。运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只能编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法

回到代码中
对于byte、short、long、char、boolean对应的包装类都有对应的常量池,这五种包装器类默认创建在-128到127的对象会存放在在缓存中。
对于两种浮点数没有实现常量池技术。
c,d的值是3,在常量池的范围内,给Integer赋值一个int类型时,它会调用一个valueOf()的方法,相当于Integer a = Integer.valueOf(1); 所以引用对象是同一个,返回true
而e,f的值超出了常量池的范围,会new对象,所以是两个对象,返回false

再看到c == (a + b),g == (a + b)这两个判断
当在一项操作中混合使用基本类型与包装类型时,包装类型会自动拆箱,在这里就是Integer拆箱成int,Long拆箱成long,所以比较的就是两个值了,值是相等的,所以返回true

最后看到c.equals(a + b),g.equals(a + b)这一组
equals()方法不处理数据转型的关系
这里我猜测是加法进行了拆箱,然后equals恢复到装箱,所以c.equals(a + b)返回true,因为Integer都是同一个引用,而Long类型的引用显然和Integer的引用不一样,所以返回false

这里再多看一个别人的例子理解常量池
在这里插入图片描述
同样把结果注释在上方
hello,lo是指向date segment的字符串常量,“Hello”,“lo"是储存在date segment的字符串常量
当"Hel+lo时,JVM内部做字符串连接,然后将连接的结果保存到heap的一块区域(也就是创建了新对象),
当"Hel”+“lo"时,因为两个都是字符串常量,JVM内部做字符串连接,然后将结果和所有date segment区的字符串常量作比较,如果没有发现相同字符串就将这个连接后的字符串作为常量放在date segment区,如果发现相同的就将引用指向原有的字符串常量
所以"Hello"和"Hel”+“lo"是同一块date segment区,所以"Hello”==“Hel”+"lo"是true
因为hel+“lo"是放在heap区的新对象,所以"hello”==hel+"lo"是false
而最后一个,String.intern(),编译器会将字符串添加到常量池中并返回指向该常量的引用,hello指向的也是常量池,所以返回的是true

总结一下,包装类的 "=="运算在不遇到算术运算的情况下不会自动拆箱,以及它们equals()方法不处理数据转型的关系,因此不建议这样使用自动装箱与拆箱。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值