Java中“100=100”为True,而"1000=1000"为False?

开发 前端
今天跟大家聊一个有趣的话题,在Java中两个Integer对象做比较时,会产生意想不到的结果。

前言

今天跟大家聊一个有趣的话题,在Java中两个Integer对象做比较时,会产生意想不到的结果。

例如:

Integer a = 100;
Integer b = 100;
System.out.println(a==b);

其运行结果是:true。

而如果改成下面这样:

Integer a = 1000;
Integer b = 1000;
System.out.println(a==b);

其运行结果是:false。

看到这里,懵了没有?

为什么会产生这样的结果呢?

1、Integer对象

上面例子中的a和b,是两个Integer对象。

而非Java中的8种基本类型。

8种基本类型包括:

  • byte
  • short
  • int
  • long
  • float
  • double
  • boolean
  • char

Integer其实是int的包装类型。

在Java中,除了上面的这8种类型,其他的类型都是对象,保存的是引用,而非数据本身。

Integer a = 1000;
Integer b = 1000;

可能有些人认为是下面的简写:

Integer a = new Integer(1000);
Integer b = new Integer(1000);

这个想法表面上看起来是对的,但实际上有问题。

在JVM中的内存分布情况是下面这样的:

在栈中创建了两个局部变量a和b,同时在堆上new了两块内存区域,他们存放的值都是1000。

变量a的引用指向第一个1000的地址。

而变量b的引用指向第二个1000的地址。

很显然变量a和b的引用不相等。

既然两个Integer对象用==号,比较的是引用是否相等,但下面的这个例子为什么又会返回true呢?

Integer a = 100;
Integer b = 100;
System.out.println(a==b);

不应该也返回false吗?

对象a和b的引用不一样。

Integer a = 1000;
Integer b = 1000;

其实正确的简写是下面这样的:

Integer a = Integer.valueOf(1000);
Integer b = Integer.valueOf(1000);

在定义对象a和b时,Java自动调用了Integer.valueOf将数字封装成对象。

而如果数字在low和high之间的话,是直接从IntegerCache缓存中获取的数据。

Integer类的内部,将-128~127之间的数字缓存起来了。

也就是说,如果数字在-128~127,是直接从缓存中获取的Integer对象。如果数字超过了这个范围,则是new出来的新对象。

文章示例中的1000,超出了-128~127的范围,所以对象a和b的引用指向了两个不同的地址。

而示例中的100,在-128~127的范围内,对象a和b的引用指向了同一个地址。

所以会产生文章开头的运行结果。

为什么Integer类会加这个缓存呢?

答:-128~127是使用最频繁的数字,如果不做缓存,会在内存中产生大量指向相同数据的对象,有点浪费内存空间。

Integer a = 1000;
Integer b = 1000;

如果想要上面的对象a和b相等,我们该怎么判断呢?

2、判断相等

在Java中,如果使用==号比较两个对象是否相等,比如:a==b,其实比较的是两个对象的引用是否相等。

很显然变量a和b的引用,指向的是两个不同的地址,引用肯定是不相等的。

因此下面的执行结果是:false。

Integer a =  Integer.valueOf(1000);
Integer b = Integer.valueOf(1000);
System.out.println(a==b);

由于1000在Integer缓存的范围之外,因此上面的代码最终会变成这样:

Integer a =  new Integer(1000);
Integer b = new Integer(1000);
System.out.println(a==b);

如果想要a和b比较时返回true,该怎么办呢?

答:调用equals方法。

代码改成这样的:

Integer a = Integer.valueOf(1000);
Integer b = Integer.valueOf(1000);
System.out.println(a.equals(b));

执行结果是:true。

其实equals方法是Object类的方法,所有对象都有这个方法。

它的底层也是用的==号判断两个Object类型的对象是否相等。

不过Integer类对该方法进行了重写:

它的底层会先调用Integer类的intValue方法获取int类型的数据,然后再通过==号进行比较。

此时,比较的不是两个对象的引用是否相等,而且比较的具体的数据是否相等。

我们使用equals方法,可以判断两个Integer对象的值是否相等,而不是判断引用是否相等。

总结

Integer类中有缓存,范围是:-128~127。

Integer a = 1000;

其实默认调用了Integer.valueOf方法,将数字转换成Integer类型:

Integer a = Integer.valueOf(1000);

如果数字在-128~127之间,则直接从缓存中获取Integer对象。

如果数字在-128~127之外,则该方法会new一个新的Integer对象。

我们在判断两个对象是否相等时,一定要多注意:

  1. 判断两个对象的引用是否相等,用==号判断。
  2. 判断两个对象的值是否相等,调用equals方法判断。
责任编辑:姜华 来源: 苏三说技术
相关推荐

2015-11-23 10:09:30

Java

2021-04-26 14:00:43

Java 数据类型

2023-05-10 16:15:58

javaScript算法开发

2016-12-22 18:38:49

JavaAndroid

2019-05-17 11:15:50

芯片数据中心技术

2020-10-28 18:51:12

大屏

2012-12-25 09:30:14

MIUI小米

2015-11-04 10:32:15

京东双11

2009-09-18 08:52:42

Windows Mob开发团队

2009-06-09 08:54:17

2021-02-02 20:45:03

Pythonmath False

2012-07-11 11:05:38

Wi-Fi伦敦奥运会英国电信

2012-07-05 09:59:54

2009-11-03 18:26:52

2017-10-12 11:23:51

阿里云1000万企业

2021-07-18 07:36:36

网络攻击恶意软件网络安全

2010-12-28 09:57:11

SymbianQtMeeGo

2019-09-20 09:35:15

百度

2011-04-20 14:28:27

软件平台SOA平台化

2022-05-26 15:00:36

翻译模型谷歌
点赞
收藏

51CTO技术栈公众号