Java中的装箱和拆箱
突然想起之前瞄过一眼的装箱和拆箱,想起概念不是特别清楚,于是探究一下。
装箱和拆箱的概念
众所周知,Java中万物皆对象(Object)。而装箱和拆箱就是处理基本数据类型和其对象之间的关系的操作。
装箱:将基本类型转化成对应的Object类型。
拆箱:将Object类型转化为对应的基本类型。
Java中的8种基本数据类型和其对应的Object类型:byte(Byte),char(Character),boolean(Boolean),short(Short),int(Int),long(Long),float(Float),double(Double)。
其相互转化就是所谓的装箱和拆箱了。
装箱和拆箱的实现
样例的引出
目前Java提供隐士的装箱和拆箱。即基本数据类型和其Object类型之间可以直接比较:
public static void main(String[] args) {
int a = 10;
Integer A = 10;
System.out.println(a == A ? "a == A" : "a != A");
int b = 1000;
Integer B = 1000;
System.out.println(a > B ? "a > B" : "a <= B");
}
//----Output
a == A
a <= B
反编译的分析
将编译后的.class反编译一下(javap -c 命令):
图片里大概分析了一下,下半部分都是一个意思,看到这些东西,应该就清楚装箱和拆箱是什么了:
- 装箱:就是Integer类调用了valueOf方法来将基本数据类型int实例化了。
- 拆箱:就是Integet类调用了intValue方法来将获得对应的基本数据类型int。
- 这些我们都没有手动去写,是编译器自己帮我们实现了。所以说,现在Java已经不需要手动的装箱和拆箱,实现了自动拆装箱了。
如果看的不是太懂的,看一下idea的反编译应该就清楚了:
不过我这里设置b值为1000,为什么反编译字节码之后就变成了true了呢??
(此处在文末的[注解1]处探究。)
源码的分析
结合这两个实例,应该就清楚了,Java的自动装箱和拆箱,调用了Integet类的valueOf方法,康一康这个函数的源码:
三个重载,一个静态内部类:
分析:
首先是两个重载类型:
没什么好说的,最后用的都是int的方法
调用了这个静态内部类,注意一点,根据参数的传值,也分开了不同的构造方法。
重点来了!
这里可以看出来,构造一个Integer类型是存在两种方式的:一个是直接构造一堆,另一个是用到一个构造一个,默认范围为[-128,127]。
发现的应用
这个发现有什么用呢?
看一组样例:
public static void main(String[] args) {
int a1 = 10,a2 = 10;
Integer A1 = 10,A2 = 10;
System.out.println(a1 == a2 ? "a1 == a2" : "a1 != a2");
System.out.println(a1 == A1 ? "a1 == A1" : "a1 != A1");
System.out.println(A1 == A2 ? "A1 == A2" : "A1 != A2");
int b1 = 1000,b2 = 1000;
Integer B1 = 1000,B2 = 1000;
System.out.println(b1 == b2 ? "b1 == b2" : "b1 != b2");
System.out.println(b1 == B1 ? "b1 == B1" : "b1 != B1");
System.out.println(B1 == B2 ? "B1 == B2" : "B1 != B2");
}
//-----Output
a1 == a2
a1 == A1
A1 == A2
b1 == b2
b1 == B1
B1 != B2
注解
注解1
然后我就换了一种写法:
然后对应的字节码:
猜想:可能是因为b没有用到,所以就编译器自动忽略了?而Object对象不管有没有用到,都实例了?
参考博客:
https://www.cnblogs.com/dolphin0520/p/3780005.html
https://blog.csdn.net/wanghao112956/article/details/94389402