Java 基础类型都包含对应的包装类型,具体关系如下:
基础类型 | 包装类型 |
---|---|
int | Integer |
short | Short |
byte | Byte |
long | Long |
folat | Float |
double | Double |
boolean | Boolean |
char | Character |
- 装箱:基础类型自动转包装类型
- 拆箱:包装类型自动转基础类型
// 自动装箱
Integer i = 100;
// 自动拆箱
int j = i;
其中装箱基于 valueOf() 方法,拆箱基于 xxxValue() 方法。它优点在于优化代码,部分场景下节约资源
比如 Integer 的 valueOf() 方法和 Boolean 类型的 valueOf() 方法:
// Integer
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
// Boolean
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
也就是说,-128 ~ 127 这个范围 Integer 装箱共用同一块内存,Boolean 相同类型的共用同一块内存。
装箱操作需要提前创建好一部分对象,无论有没有使用,会带来轻微的内存损耗。
拆箱操作没做任何特殊处理,直接返回值
基础类型和引用类型比较时:
- “==" 触发拆箱操作,比较具体值
- “equals()” 触发装箱操作,由于引用类型 equals() 方法大多数已重写,还是比较具体值
需要注意的是引用类型和引用类型的 “==” 操作比较地址,下面我列出几种情况:
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean(true);
Boolean b3 = true;
Boolean b4 = true;
// b1 == b2:false,对象地址不同
// b1 == b3: false,对象地址不同
// b3 == b4: true,由于装箱,对象地址相同
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
Integer i3 = 1;
Integer i4 = 1;
Integer i5 = 200;
Integer i6 = 200;
// i1 == i2: false,对象地址不同
// i1 == i3: false,对象地址不同
// i3 == i4: true,装箱地址相同
// i5 == i6: false,虽然装箱,但由于超出范围还是走的 new
新版的 JVM 已经不建议基础引用类型对象之间通过 == 比较,大家知道原理就行了。
主要 Integer 和 Boolean 值的范围相对较控制,因此装箱时可以采用缓存,导致引用地址相同,其它基础类型值范围不好控制,使用装箱基本上和 new 没有区别