前言

今天跟大家聊一个有趣的话题,在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方法判断。

Java中“100==100”为true,而"1000==1000"为false?的更多相关文章

  1. Java中for(;;)和while(true)的区别

    while(true): public class Test { public static void main(String[] args) { while(true) { } } } 在?看看汇编 ...

  2. Java中的null

    null是Java中的关键字,像public.static.final.它是大小写敏感的,你不能将null写成Null或NULL,编译器将不能识别它们然后报错. Object obj = NULL; ...

  3. [转载] 在java中为什么变量1000 = 1000 返回false,但是100=100返回true?

    ps:题目的意思是指定义相同内容的不同变量之间的==比较.如果直接比较(100 == 100)的结果是true. 运行以下代码: Integer a = 1000, b = 1000; System. ...

  4. 为什么 Java中1000==1000为false而100==100为true?AND "2+2=5"?

    前提:我们知道,如果两个引用指向同一个对象,用==表示它们是相等的.如果两个引用指向不同的对象,用==表示它们是不相等的,即使它们的内容相同. 运行下面代码:

  5. Integer中1000==1000为false而100==100为true

    查看Integer.java类,会发现有一个内部私有类,IntegerCache.java,它缓存了从-128到127之间的所有的整数对象.如果在这个区间内,他就会把变量当做一个变量,放到内存中:但如 ...

  6. Java-学习日记(100 == 100为true,1000 == 1000却为false?)

    Integer底层设计 100 == 100为true,1000 == 1000却为false? 之前也写过String的==与equals的注意点,这次写下Integer的底层设计,不妨先运行下下面 ...

  7. 实现java 中 list集合中有几十万条数据,每100条为一组取出

    解决"java 中 list集合中有几十万条数据,每100条为一组取出来如何实现,求代码!!!"的问题. 具体解决方案如下: /** * 实现java 中 list集合中有几十万条 ...

  8. jvm常量池 vsv为什么1000 == 1000返回为False,而100 == 100会返回为True?

    在jvm规范中,每个类型都有自己的常量池.常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型.字段.方法的符号引用.之所以是符号引用而不是像c语言那样,编译时直接 ...

  9. jQuery中的100个技巧

      1.当document文档就绪时执行JavaScript代码. 我们为什么使用jQuery库呢?原因之一就在于我们可以使jQuery代码在各种不同的浏览器和存在bug的浏览器上完美运行. < ...

  10. 【Todo】Java学习笔记 100==100 & Reflection API & Optional类详解 & DIP、IoC、DI & token/cookie/session管理会话方式

    为什么1000 == 1000返回为False,而100 == 100会返回为True?   Link Java Reflection API:Link Java8 Optional 类深度解析: L ...

随机推荐

  1. RocketMQ 系列(二) 环境搭建

    RocketMQ 系列(二) 环境搭建 上一个章节对于 RocketMQ 作了一些概念上的介绍,如果你对于 RocketMQ 没有概念,不妨先看RocketMQ系列(一) 基本介绍. 这个章节主要介绍 ...

  2. 文心一言 VS 讯飞星火 VS chatgpt (86)-- 算法导论8.2 3题

    三.用go语言,假设我们在 COUNTING-SORT的第 10行循环的开始部分,将代码改写为: 10 for j = 1 to A.length 试证明该算法仍然是正确的.它还稳定吗? 文心一言: ...

  3. MySQL数据库触发器讲解 [创建/删除/查询/select into]

    刚学习实例完mysql触发器, 前来分享学习经验.    菜鸟装逼,  老鸟勿喷 先来认识一下有关触发器的一些关键词.  在使用触发器时, 这些关键词将被用到, 请记下它们的模样和用途(意思) cre ...

  4. 每日一库:Prometheus

    什么是 Prometheus Prometheus 是一个开源的系统监控和警报工具,最初由 SoundCloud 开发,并于 2012 年发布为开源项目.它是一个非常强大和灵活的工具,用于监控应用程序 ...

  5. 基于三菱Q系列cc-Link的卧式自动燃煤蒸汽锅炉控制系统

    系统说明: 方案选用: 本系统最终采用三菱Q系列+FX3U系列方案 工艺流程: 触摸屏设计: 程序设计: 本文章为原创作品,未经允许,请勿转载,否则将会追究法律责任.

  6. 【Qt6】列表模型——树形列表

    QStandardItemModel 类作为标准模型,主打"类型通用",前一篇水文中,老周还没提到树形结构的列表,本篇咱们就好好探讨一下这货. 还是老办法,咱们先做示例,然后再聊知 ...

  7. 人工智能AI绘画全攻略(AI绘画教程分享)

    在过去的三个月一直在研究人工智能生成绘画这个方向,3 月份的时候参加了小红书的小航海,也因为这个方向的选择正好对应到了趋势,小红书在一个半月做到了 1 万粉.我为什么看好这个方向? 主要是从三个方面: ...

  8. 铅华洗尽,粉黛不施,人工智能AI基于ProPainter技术去除图片以及视频水印(Python3.10)

    视频以及图片修复技术是一项具有挑战性的AI视觉任务,它涉及在视频或者图片序列中填补缺失或损坏的区域,同时保持空间和时间的连贯性.该技术在视频补全.对象移除.视频恢复等领域有广泛应用.近年来,两种突出的 ...

  9. [ABC212E] Safety Journey 题解

    Safety Journey 题目大意 给定一张缺少了 \(m\) 条边的 \(n\) 个点的完全图和一个正整数 \(k\),你需要求出满足以下条件的序列 \(A\) 的数量: \(A\) 的长度为 ...

  10. Hall定理(霍尔定理)证明及推广

    引言 网络上有许多Hall定理的证明,但是对于Hall定理的几个推广的介绍却少之又少,因此本文来简单介绍一下 注:为了使这篇文章看起来简单易懂,本文将不会使用图论语言,会图论的朋友们可以自行翻译为图论 ...