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