基本数据类型
基本数据类型的好处
- 在Java语言中,new一个对象是存储在堆里的,我们通过栈中的引用来使用这些对象;所以,对象本身来说是比较消耗资源的。
- 基本数据类型不使用new创建,不存储在堆里,而是直接在栈中存储,因此会更加高效。
包装类
基本数据类型 | 包装类 |
---|---|
char | Character |
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
自动装箱与自动拆箱
- 基本数据类型转换成包装类的过程就是打包装,英文是boxing,翻译为装箱。
- 包装类转换成基本数据类型的过程就是拆包装,英文是unboxing,翻译为拆箱。
自动装箱与自动拆箱的实现原理
自动拆装箱的代码:
public void testBoxing() {
Character charObj = 'a';
char charVal = charObj;
Boolean booleanObj = true;
boolean booleanVal = booleanObj;
Byte byteObj = 1;
byte byteVal = byteObj;
Short shortObj = 1;
short shortVal = shortObj;
Integer intObj = 1;
int intVal = intObj;
Long longObj = 1l;
long longVal = longObj;
Float floatObj = 1f;
float floatVal = floatObj;
Double doubleObj = 1d;
double doubleVal = doubleObj;
}
反编译后得到:
public void testBoxing() {
Character character = Character.valueOf('a');
char c = character.charValue();
Boolean bool = Boolean.valueOf(true);
boolean bool1 = bool.booleanValue();
Byte byte_ = Byte.valueOf((byte)1);
byte b = byte_.byteValue();
Short short_ = Short.valueOf((short)1);
short s = short_.shortValue();
Integer integer = Integer.valueOf(1);
int i = integer.intValue();
Long long_ = Long.valueOf(1L);
long l = long_.longValue();
Float float_ = Float.valueOf(1.0F);
float f = float_.floatValue();
Double double_ = Double.valueOf(1.0D);
double d = double_.doubleValue();
}
可以看出,自动装箱都是通过包装类的valueOf()方法来实现的,自动拆箱都是通过包装类对象的xxxValue()来实现的。
自动装箱拆箱容易混淆的场景
场景一,包装类型和基本类型的比较,包装类型进行自动拆箱。
Integer a = 300;
System.out.println(a == 1 ? "等于" : "不等于");
Boolean bool = false;
System.out.println(bool ? "真" : "假");
反编译后:
Integer a = Integer.valueOf(300);
System.out.println((a.intValue() == 1) ? ": ");
Boolean bool = Boolean.valueOf(false);
System.out.println(bool.booleanValue() ? ": ");
场景二,包装类型的计算,包装类型自动拆箱。
Integer i = 10;
Integer j = 20;
System.out.println(i + j);
反编译后:
Integer i = Integer.valueOf(10);
Integer j = Integer.valueOf(20);
System.out.println(i.intValue() + j.intValue());
场景三,三目运算符,混合基本类型时,包装类型自动拆箱;若接收值是包装类型,则结果自动装箱。
boolean b = true;
int k1 = b ? i : j;
int k2 = b ? i : 20;
Integer k3 = b ? i : j;
Integer k4 = b ? i : 20;
反编译后:
boolean b = true;
int k1 = (b ? i : j).intValue();
int k2 = b ? i.intValue() : 20;
Integer k3 = b ? i : j;
Integer k4 = Integer.valueOf(b ? i.intValue() : 20);
自动拆装箱与缓存
在Boxing Conversion部分的Java语言规范(JLS)规定如下:
如果一个变量p的值是:
- -128至127之间的整数(§3.10.1)
- true 和 false的布尔值 (§3.10.3)
- ‘\u0000’至 ‘\u007f’之间的字符(§3.10.4)
范围内的时,将p包装成a和b两个对象时,可以直接使用a==b判断a和b的值是否相等。
注意:这里的整数不只针对Integer,也包括Byte、Short、Long以及BigDecimal等。
自动拆装箱带来的问题
- 包装对象的数值比较,不能简单的使用==,虽然-128到127之间的数字可以,但是这个范围之外还是需要使用equals比较。
- 在自动拆箱时,如果包装类对象为null,会抛出NPE。
- 如果一个for循环中有大量拆装箱操作,会浪费很多资源。