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