Java 包装类型装箱拆箱

先来看如下一段代码的运行结果,是否符合你的预期呢?

Integer a1 = 127;
Integer a2 = 127;
Integer a3 = 128;
Integer a4 = 128;
int a5 = 128;
System.out.println(a1 == a2); // L1: true
System.out.println(a3 == a4); // L2: false
System.out.println(a3 == a5); // L3: true

基础数据类型与包装数据类型

基础类型 包装类型 意义 取值
boolean Boolean 布尔值 true 或 false
byte Byte 8bit 有符号整型 -128~127
short Short 16bit 有符号整型 ~
int Integer 32bit 有符号整型 ~
long Long 64bit 有符号整型 ~
float Float 32 位浮点数 IEEE754 标准单精度浮点数
double Double 64 位浮点数 IEEE754 标准双精度浮点数
char Character 字符型 16 位不带符号,Unicode 字符

基础类型转包装类型,用类方法 valueOf, 称为装箱; 包装类型转基础类型,用成员方法 xxxValue, 称为拆箱.

自动装箱拆箱

自动装箱拆箱机制其实是编译时自动完成替换的,装箱阶段自动替换为了 valueOf 方法,拆箱阶段自动替换为了 xxxValue 方法。 注意:-128~127 范围内的数据,比如 Boolean, Byte, 部分 Short/Integer/Long, 做 valueOf 操作时,有 cache, 会直接返回内部缓存池中已经存在对象的引用,其他范围值则返回新建对象。对于浮点数,不管传入的参数值是多少都会 new 一个对象。

代码解读

对于 L1/L2, 变量都是对象,== 比较的是对象的地址,由于 127 在 cache 范围,因此是同一个对象;而 128 不在 cache 范围,因此不是同一个对象。 如果需要做值比较,而不是引用比较,那么使用 equals 方法。

对于 L3, 变量有基础类型,这时会出发自动拆箱机制,因此本质是值比较,结果为 true.

Java 中比较操作的建议

  1. 基础数据类型比较,直接用 ==.
  2. 非空包装类型比较,用 equals, 比如 "str".equals(a).
  3. 不确定是否有空指针,用 Objects.equals