Java自动装箱和拆箱
Java中基础数据类型与它们的包装类进行运算时,编译器会自动帮我们进行转换,转换过程对程序员是透明的,装箱和拆箱可以让我们的代码更简洁易懂,本质是Java的语法糖。
- 装箱: 基本类型 => 包装类型;
- 拆箱: 包装类型 => 基本类型。
基本类型与包装类型对应
基本类型 | 包装类型 |
---|---|
boolean | Boolean |
byte | Byte |
char | Character |
float | Float |
int | Integer |
long | Long |
short | Short |
double | Double |
装箱拆箱的触发
当表格中基础类型与它们的包装类有如下几种情况时,编译器会自动帮我们进行装箱或拆箱:
- 进行 = 赋值操作(装箱或拆箱);
- 进行+,-,*,/混合运算 (拆箱);
- 进行>,<,==比较运算(拆箱);
- 调用equals进行比较(装箱);
- ArrayList,HashMap等包装类泛型对象,添加基础类型数据时(装箱).
例以下代码:
Integer i = 100
等价于Integer i = Integer.valueOf(100)
int i = new Integer(100)
等价于int i = new Integer(100).intValue()
容易踩坑的点
JVM缓存
如Integer类的valueOf(int)实现:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
可见,-128到127的Integer对象会被JVM缓存,所以有以下情况:
public static void main(String[] args) {
// 等价于 Integer i1 = Integer.valueOf(100);
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1 == i2);
System.out.println(i3 == i4);
}
// -------------------输出-------------------
// true
// false
通过自动装箱,i1和i2指向cache中同一个对象,i3和i4指向两个对象。
valueOf的不同实现
以Double为例
public static void main(String[] args) {
Double d1 = 1.0;
Double d2 = 1.0;
Double d3 = 11111.0;
Double d4 = 11111.0;
System.out.println(d1 == d2);
System.out.println(d3 == d4);
}
// -------------------输出-------------------
// false
// false
至于具体原因,可见Double类的valueOf的实现。
public static Double valueOf(double d) {
return new Double(d);
}
需要记住:
- Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
- Double、Float的valueOf方法的实现是类似的。
如此设计的原因:在某个范围内的整型数值的个数是有限的,而浮点数却不是。