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

避免因为缓存机制导致逻辑错误。


更多推荐