先来看如下一段代码的运行结果,是否符合你的预期呢?
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 中比较操作的建议
- 基础数据类型比较,直接用
==
. - 非空包装类型比较,用
equals
, 比如"str".equals(a)
. - 不确定是否有空指针,用
Objects.equals