Java装箱和拆箱
什么是装箱和拆箱
首先要清楚Java为8种基本类型都提供了对应的包装类
装箱和拆箱是Java5提供的特性,装箱简单来说就是直接将基本类型转换为包装类,拆箱简单来说就是直接将包装类转换为基本类型,举个例子:
public class Main {
public static void main(String[] args) {
//Java5之间需要使用new操作创建新的Integer
Integer int1 = new Integer(10);
//Java5之后直接将数字赋值即可
Integer int2 = 10;
//Java5之前需要使用intValue()将Integer转换为int
int int3 = int1.intValue();
//Java5之后之间赋值即可
int int4 = int2;
}
}
注意点:
上面装箱和拆箱实际上也是通过valueOf()和intValue()方法实现的
常量池
基本类型的常量池
经常写代码可能会发现以下的情况
public class Main {
public static void main(String[] args) {
Integer int1 = 100;
Integer int2 = 100;
System.out.println(int1 == int2);
}
}
output:true
明明是从堆里面申请的两个对象,为什么地址会一样呢?
首先,上面的操作真的是从堆中申请的对象吗?
已知装箱过程是用**valueOf()实现的,查看valueOf()**的源码
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
return i >= -128 && i <= Integer.IntegerCache.high Integer.IntegerCache.cache[i + 128] : new Integer(i);
}
可以看到,当int的值在**[-128 , 127]中的时候是通过IntegerCache来获取的,即Integer中已经申请了值在[-128 , 127]的对象在常量池中,当我们装箱子的时候会直接返回对应的对象,这就是为什么上面的输出是true**,而当值在**[-128,127]**之外的时候:
public class Main {
public static void main(String[] args) {
Integer int1 = 130;
Integer int2 = 130;
System.out.println(int1 == int2);
}
}
output:false
除了Interger之外,其他的部分包装类也有对应的常量池:
包装类 | 常量池 |
---|---|
Integer | [-128,127] |
Byte | [-128,127] |
Short | [-128,127] |
Long | [-128,127] |
Boolean | {True , False} |
Character | [0,127] |
运算
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = new Integer(3);
System.out.println(c==(a+b));
}
}
output:
true
上面的代码输出也是true
在进行加减乘除的运算操作的时候也是调用拆箱操作,然后在**==操作中,有一边是表达式,比较的是数值,所以c**也会被拆箱
ps:String类也实现了常量池技术,有兴趣的话可以思考一下为什么下面的代码的输出是这样的
public class Main {
public static void main(String[] args) {
String str1 = "hello world";
String str2 = "hello world";
String str3 = new String("hello word");
System.out.println(str1 == str2);
System.out.println(str3 == str1);
}
}
output:
true
false