前言
本博客主要涉及以下几个内容:
- 装箱与拆箱
- 装箱生成的Integer在哪里
- 案例
装箱与拆箱
Java中有八种基本数据类型: byte, short, int, long, float, double, char, boolean。这八种基本数据类型对应着八个包装类,基本数据类型转换为包装类叫做装箱,反之叫做拆箱。
为什么要进行装箱和拆箱?
Java中最主要有三类存储空间: 栈,堆,方法区。栈中存基本数据类型和堆中对象的引用;堆中一般存放运行时的动态数据,最主要有new
出来的对象;方法区中存储的数据不是本文的重点,就不细说了,本文只涉及方法区中的常量池,常量池中存储的是常量。
基本数据类型因为经常被使用,所以为了提高效率,都放在栈中进行运算;但是栈中的数据并不具备持久性,对于Java中同样经常使用的容器,栈中的数据显然不具备放入容器中的资格,因此才有了装箱和拆箱的步骤。JDK5后,Java实现了自动装箱和拆箱。
如何进行装箱和拆箱
这里不放java反编译后的结果了,直接说结论。只给出int
和Integer
之间的转换。
- 代码
1 | Integer in = 9; //装箱 |
- 装箱调用:
Integer in = Integer.valueOf(9)
1 | public static Integer valueOf(int i) { |
- 拆箱调用:
int i = in.intValue()
1 | public int intValue() { |
装箱生成的Integer去了哪里?
上面的源码引出了一个新的类IntegerCache
, 这个类是Integer
类的静态内部类,内部存在三个常量:
1 | static final int low = -128; |
常量high
会在类中的静态代码块中被赋值为127
,cache[]
中存储了value
为-128 ~ 127
的Integer
包装类。
由源码可知:当装箱的int
值在-128 ~ 127
中时,Integer
会直接返回常量池中的对象,而这些对象,在Integer
类加载的时候就被创建了,因此不会再开辟多余的空间。而当int
的值超过范围,则会在堆中重新开辟Integer
对象的空间。
案例
1 | int a = 99; |
解释:
A
和AA
都指向常量池中的Integer
对象B
和BB
都是在执行装箱操作后new
出来的Integer
对象,因此地址不同