在介绍本期文章内容之前,让我们先来看一小段代码:
int a = 10;
Integer b = 10;
if(b == a){
System.out.println("相等");
}
执行结果应该大家是毋庸置疑的,10等于10,自然会输出相等。但是有一个问题,a明明是int类型,而b则是Integer类型。两个明显是不同类型的对象,为什么能够相等呢?这就涉及到我们这次要介绍的内容:拆箱、装箱
简介
首先,简单介绍下装箱、拆箱的含义:
装箱,指基础类型(int、double等)转换成包装类型(Integer、Double等)的过程
拆箱,顾名思义同装箱相反,是从包装类型转换到基础类型的过程。
在JDK1.5以前,还不存在装箱、拆箱的概念。因此,对于基本类型同包装类型的转换,基本只能通过代码手写实现。
ini 代码解读复制代码 Boolean a = Boolean.valueOf(true);
Integer b = Integer.valueOf(10);
然而,懒惰是推动人类社会进步的动力。时间一长了,大家就发现:
“明明这两个类型都是表达相似含义的东西,有没有什么办法把这两个的转换隐藏起来呢?这样我就不用写着么多代码了呀”
实现原理
结合上述对于拆箱装箱的介绍,我们不难分析出来,要实现拆箱和装箱,至少需要考虑两点:
什么时候做拆箱装箱?
怎么做拆箱装箱?
啥时候拆箱装箱
首先明确一点,装箱和拆箱是指发生在基本类型与包装类型之间的。如果一个类根本都不存在包装类型 or 基本类型,那么肯定是不会发生拆箱装箱的。在Java中,同时存在基本类型和包装类型的有如下几个:
基本类型包装类型booleanBooleanbyteByteintIntegershortShortcharCharacterlongLongfloatFloatdoubleDouble
那么在知道了有哪些类型存在包装类和基本类后。我们还需要知道装箱和拆箱触发的时机。简单来说主要分为以下几个:
1、赋值
2、调用方法
3、数值计算
设值,这个主要就是讲的将基本类型的数值赋值给包装类型,如下代码所示:
ini 代码解读复制代码 Integer b = 10;
调用方法,主要指的是方法的入参为包装类型,传入的实际上是基本类型的情况,以Integer类型为例子,调用方法产生装箱拆箱的情况如下所示:
public static void main(String[] args) {
//产生装箱、拆箱
transform(1);
}
public static void transform(Integer b){
System.out.println(b);
}
最后一种情况,主要指的是基本类型同包装类型做计算的时候会发生拆箱。具体例子如下所示:
ini 代码解读复制代码 public static void main(String[] args) {
Integer b = 10;
int ab = 20;
int i = b + ab; // b调用拆箱的方法
}
怎么做拆箱装箱
装箱
在明确了拆箱装箱的时机以后,就是考虑如何实现转化了。实际上,在由编译.java的过程中,编译器会将特定的包装类型调用对应的转化方法,下面以具体的代码为例子:
ini 代码解读复制代码 Boolean a = true;
Integer b = 10;
通过将上述代码的.class文件进行反编译(调用代码javap -c xxx.class),可以得到如下的反编译代码:
yaml 代码解读复制代码 public class com.example.demo.DemoApplication {
public com.example.demo.DemoApplication();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."