【Java 知识点详解 7】装箱和拆箱
Integer i = 10;
int n = i;
}
}
反编译 class 文件之后得到如下内容:
从反编译的字节码中可以看出,在装箱的时候自动调用的是 interger 的 valueOf(int)方法。而在拆箱的时候自动调用的是 interger 的 intValue 方法
因此用一句话总结装箱和拆箱的实现过程:
装箱过程是通过调用包装器的 valueOf 方法实现的,而拆箱过程是通过引用类型调用 xxxValue 实现的。
三、面试中的相关问题
虽然大多数人对装箱和拆箱的概念都清楚,但是在面试和笔试中遇到了与装箱和拆箱的问题却不一定会答得上来。下面列举一些常见的与装箱/拆箱有关的面试题。
1、下面这段代码的输出结果是什么?
public class Main {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2);
System.out.println(i3==i4);
}
}
也许有些朋友会说都会输出 false,或者也有朋友会说都会输出 true。但是事实上输出结果是:
true
false
为什么会出现这样的结果?输出结果表明 i1 和 i2 指向的是同一个对象,而 i3 和 i4 指向的是不同的对象。此时只需一看源码便知究竟,下面这段代码是 Integer 的 valueOf 方法的具体实现:
public static Interger valueOf(int i){
if(i>=-128&&i<=IntergerCache.high){
return IntergerCache.cache[i+128];
}else{
return new Interger(i);
}
}
通过 valueOf 方法创建 Integer 对象的时候,如果数值在[-128,127]之间,便返回指向 IntegerCache.cache 中已经存在的对象的引用;否则创建一个新的 Integer 对象。
上面的代码中 i1 和 i2 的数值为 100,因此会直接从 cache 中取已经存在的对象,所以 i1 和 i2 指向的是同一个对象,而 i3 和 i4 则是分别指向不同的对象。
其它的引用类型,可以去查看 valueOf 的实现。
******************************************************************************
弦外音:八种数据类型取值范围
整型:
byte:-2^7 ~ 2^7-1,即-128 ~ 127。1 字节。Byte。末尾加 B
short:-2^15 ~ 2^15-1,即-32768 ~ 32767。2 字节。Short。末尾加 S
int:-2^31 ~ 2^31-1,即-2147483648 ~ 2147483647。4 字节。Integer。
long:-2^63 ~ 2^63-1,即-9223372036854774808 ~
9223372036854774807。8 字节。Long。末尾加 L。(也可以不加 L)
浮点型:
float:4 字节。Float。
double:8 字节。Double。
字符型:
char:2 字节。Character。
布尔型:
boolean:Boolean。
类型转换:
boolean 类型与其他基本类型不能进行类型的转换(既不能进行自动类型的提升,也不能强制类型转换), 否则,将编译出错。
byte 型不能自动类型提升到 char,char 和 short 直接也不会发生自动类型提升(因为负数的问题),同时,byte 当然可以直接提升到 short 型。
当对小于 int 的数据类型(byte, char, short)进行运算时,首先会把这些类型的变量值强制转为 int 类型进行计算,最后会得到 int 类型的值。因此,如果把 2 个 short 类型的值相加,最后得到的结果是 int 类型,如果需要得到 short 类型的结果,就必须显示地运算结果转为 short 类型。
******************************************************************************
下面程序的输出结果是什么?
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c==d);//true
System.out.println(e==f);//false
System.out.println(c==(a+b));//true
System.out.println(c.equals(a+b));//true
System.out.println(g==(a+b));//true
System.out.println(g.equals(a+b));//false
System.out.println(g.equals(a+h));//true
}
}
当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals 方法并不会进行类型转换。
评论