Java面试高频题:Integer缓存机制与 equals、== 区别
Java面试高频题:Integer缓存机制与 equals、== 区别
在 Java 面试中,包装类是必考知识点,而 Integer 缓存机制更是高频中的高频。
例如下面这段代码:
Integer a = 127; Integer b = 127; System.out.println(a == b);输出:
true但是:
Integer a = 128; Integer b = 128; System.out.println(a == b);输出:
false为什么会出现这种现象?
本文将从包装类、自动装箱、Integer缓存池以及 equals 和 == 的区别几个方面深入分析。
目录
- 为什么需要包装类
- 八大包装类
- 自动装箱与自动拆箱
- == 与 equals 的区别
- Integer缓存机制
- 为什么127返回true
- 为什么128返回false
- Integer源码分析
- 常见面试题
- 开发最佳实践
- 总结
一、为什么需要包装类
Java中的基本数据类型:
byte
short
int
long
float
double
char
boolean
这些类型虽然效率高,但存在局限性。
例如:
List<int> list = new ArrayList<>();
编译直接报错。
因为泛型只能使用对象。
因此Java为每种基本类型提供了对应的包装类。
二、八大包装类
| 基本类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
示例:
Integer age = 18;
Double salary = 10000.5;
三、自动装箱与自动拆箱
JDK5之后引入了自动装箱机制。
自动装箱
代码:
Integer num = 100;
实际上:
Integer num = Integer.valueOf(100);
编译器自动完成转换。
自动拆箱
代码:
Integer num = 100;
int value = num;
实际上:
int value = num.intValue();
示例
Integer a = 10;
Integer b = 20;
System.out.println(a + b);
执行过程:
自动拆箱
↓
int运算
↓
自动装箱(如果需要)
四、== 与 equals 的区别
这是面试中的经典问题。
== 比较什么?
对于基本类型:
int a = 10;
int b = 10;
a == b
比较的是:
值
结果:
true
对于引用类型:
String s1 = new String("abc");
String s2 = new String("abc");
s1 == s2
比较的是:
对象地址
结果:
false
因为是两个不同对象。
equals比较什么?
Object源码:
public boolean equals(Object obj) {
return (this == obj);
}
默认也是比较地址。
但是很多类重写了equals。
例如:
String
Integer
Long
BigDecimal
Date
等。
示例:
String s1 = new String("abc");
String s2 = new String("abc");
s1.equals(s2)
结果:
true
因为String重写了equals。
比较的是内容。
五、Integer缓存机制
Integer为了提高性能,避免频繁创建对象,引入了缓存池。
缓存范围:
-128 ~ 127
这也是面试最常考的知识点。
例如:
Integer a = 100;
Integer b = 100;
实际上:
Integer.valueOf(100)
会从缓存池获取对象。
因此:
a == b
结果:
true
六、为什么127返回true
示例:
Integer a = 127;
Integer b = 127;
比较:
System.out.println(a == b);
输出:
true
执行过程:
Integer.valueOf(127)
发现:
127
属于缓存范围
直接返回缓存对象。
图示:
IntegerCache
↓
127对象
↑ ↑
a b
因此:
a和b指向同一个对象
结果:
a == b
为:
true
七、为什么128返回false
代码:
Integer a = 128;
Integer b = 128;
比较:
System.out.println(a == b);
输出:
false
原因:
128
超出缓存范围
执行:
Integer.valueOf(128)
时:
创建新对象
图示:
a
↓
Integer(128)
──────────
b
↓
Integer(128)
两个对象地址不同。
因此:
a == b
结果:
false
八、源码分析
查看 Integer 源码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low &&
i <= IntegerCache.high) {
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
核心逻辑:
如果在缓存范围
直接返回缓存对象
否则创建新对象
继续查看缓存范围:
static final int low = -128;
static final int high = 127;
因此:
-128 ~ 127
被缓存。
九、new Integer为什么不同
示例:
Integer a = new Integer(127);
Integer b = new Integer(127);
比较:
System.out.println(a == b);
结果:
false
原因:
new
强制创建新对象。
不会走缓存池。
图示:
a → 对象A
b → 对象B
地址不同。
十、Integer与int比较
示例:
Integer a = 128;
int b = 128;
System.out.println(a == b);
结果:
true
原因:
发生自动拆箱。
实际执行:
a.intValue() == b
变成:
128 == 128
比较的是值。
因此:
true
十一、常见面试陷阱
示例1
Integer a = 127;
Integer b = 127;
System.out.println(a == b);
结果:
true
示例2
Integer a = 128;
Integer b = 128;
System.out.println(a == b);
结果:
false
示例3
Integer a = 128;
Integer b = 128;
System.out.println(a.equals(b));
结果:
true
示例4
Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b);
结果:
false
示例5
Integer a = 100;
int b = 100;
System.out.println(a == b);
结果:
true
十二、常见面试题
面试题1
Integer缓存范围是多少?
答案:
-128 ~ 127
面试题2
为什么127==127返回true?
答案:
使用缓存对象
地址相同
面试题3
为什么128==128返回false?
答案:
超出缓存范围
创建两个新对象
面试题4
equals和==区别?
答案:
==
基本类型比较值
引用类型比较地址
equals
默认比较地址
很多类重写后比较内容
面试题5
Java存在引用传递吗?
答案:
没有
Java只有值传递
十三、开发最佳实践
1、对象比较优先使用equals
推荐:
Integer a = 128;
Integer b = 128;
a.equals(b);
不推荐:
a == b
因为容易受到缓存机制影响。
2、字符串比较使用equals
推荐:
str1.equals(str2);
不推荐:
str1 == str2;
3、注意自动拆箱空指针
例如:
Integer num = null;
int value = num;
运行:
NullPointerException
原因:
num.intValue();
空指针异常。
总结
本文介绍了:
- 包装类的作用
- 自动装箱与拆箱
- == 与 equals 区别
- Integer缓存机制
- 为什么127返回true
- 为什么128返回false
- Integer源码分析
- 面试高频陷阱题
需要牢记:
Integer缓存范围:
-128 ~ 127
以及:
对象比较优先使用equals
避免因为缓存机制导致逻辑错误。
更多推荐

所有评论(0)