Java中“100==100”为true,而"1000==1000"为false?
前言
今天跟大家聊一个有趣的话题,在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对象。
我们在判断两个对象是否相等时,一定要多注意:
- 判断两个对象的引用是否相等,用==号判断。
- 判断两个对象的值是否相等,调用equals方法判断。
Java中“100==100”为true,而"1000==1000"为false?的更多相关文章
- Java中for(;;)和while(true)的区别
while(true): public class Test { public static void main(String[] args) { while(true) { } } } 在?看看汇编 ...
- Java中的null
null是Java中的关键字,像public.static.final.它是大小写敏感的,你不能将null写成Null或NULL,编译器将不能识别它们然后报错. Object obj = NULL; ...
- [转载] 在java中为什么变量1000 = 1000 返回false,但是100=100返回true?
ps:题目的意思是指定义相同内容的不同变量之间的==比较.如果直接比较(100 == 100)的结果是true. 运行以下代码: Integer a = 1000, b = 1000; System. ...
- 为什么 Java中1000==1000为false而100==100为true?AND "2+2=5"?
前提:我们知道,如果两个引用指向同一个对象,用==表示它们是相等的.如果两个引用指向不同的对象,用==表示它们是不相等的,即使它们的内容相同. 运行下面代码:
- Integer中1000==1000为false而100==100为true
查看Integer.java类,会发现有一个内部私有类,IntegerCache.java,它缓存了从-128到127之间的所有的整数对象.如果在这个区间内,他就会把变量当做一个变量,放到内存中:但如 ...
- Java-学习日记(100 == 100为true,1000 == 1000却为false?)
Integer底层设计 100 == 100为true,1000 == 1000却为false? 之前也写过String的==与equals的注意点,这次写下Integer的底层设计,不妨先运行下下面 ...
- 实现java 中 list集合中有几十万条数据,每100条为一组取出
解决"java 中 list集合中有几十万条数据,每100条为一组取出来如何实现,求代码!!!"的问题. 具体解决方案如下: /** * 实现java 中 list集合中有几十万条 ...
- jvm常量池 vsv为什么1000 == 1000返回为False,而100 == 100会返回为True?
在jvm规范中,每个类型都有自己的常量池.常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型.字段.方法的符号引用.之所以是符号引用而不是像c语言那样,编译时直接 ...
- jQuery中的100个技巧
1.当document文档就绪时执行JavaScript代码. 我们为什么使用jQuery库呢?原因之一就在于我们可以使jQuery代码在各种不同的浏览器和存在bug的浏览器上完美运行. < ...
- 【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 ...
随机推荐
- 机器学习(6)K近邻算法
k-近邻,通过离你最近的来判断你的类别 例子: 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近的样本中大多数属于某一类别),则该样本属于这个类别 K近邻需要做标准化处理 例如: imp ...
- MySQL实战实战系列 03 事务隔离:为什么你改了我还看不见?
提到事务,你肯定不陌生,和数据库打交道的时候,我们总是会用到事务.最经典的例子就是转账,你要给朋友小王转 100 块钱,而此时你的银行卡只有 100 块钱. 转账过程具体到程序里会有一系列的操作,比如 ...
- Blazor Server 发起HttpPost请求,但是多参数
一.介绍 今天突然想起之前工作上遇到的一个问题,在做Blazor 开发时后端给的一个接口请求方式是Post ,但是他需要携带多个参数,新建一个公共类又觉得麻烦,我就尝试着怎么在Post请求中携带多个参 ...
- 每日一题:vue3自定义指令大全(呕心沥血所作,附可运行项目源码)
1.VUE常用指令大全 本项目所有指令均为全局注册,使用时直接在组件中使用即可. 指令目录:src/directives 页面目录:src/views 具体可查看源码 1.1 权限指令 封装一个权限指 ...
- 将Python程序打包成Linux可执行文件
将Python程序打包成Linux可执行文件 安装环境 首先我们要安装pip,命令如下: sudo apt install python3-pip 使用的工具是pyinstaller,打开终端输入su ...
- elmentui表单重置初始值问题与解决方法
背景 在做管理台项目时,我们会经常使用到表单+表格+弹窗表单的组合,以完成对数据的增.删.查.改. 在vue2+elementui项目中,使用弹窗dialog+表单form,实现对数据的添加和修改. ...
- Go 语言的前生今世与介绍
Go 语言的前生今世与介绍 目录 Go 语言的前生今世与介绍 一. Go 语言的发展 1.1 Go 语言是如何诞生的? 1.2 Go语言的早期团队和演进历程 1.3 Go语言正式发布并开源 1.4 G ...
- android开发阶段性技能
一.初级 1. 拥有娴熟的Java基础,理解设计模式,比如OOP语言的工厂模式要懂得. 2. 掌握Android UI控件.Android Java层API相关使用. 迈向中级,最好再次更新下Java ...
- JavaScript:用户代理检测:通过浏览器识别平台、操作系统等(Windows, Mac, iOS,iPad等)
客户端检测经常用的方法:能力检测.怪癖检测和用户代理检测. 能力检测:在写代码前先检测浏览器的能力. 怪癖检测:实际上是浏览器现存的bug. 用户代理检测:通过检测用户代理字符串来识别浏览器. 一般优 ...
- logback java动态配置【动态修改日志级别,动态修改appender】(转)
logback 动态配置 写在前面在做java日志之前,强烈建议大家读一下这篇java日志的前世今生,对理清java日志框架很有帮助!1奉上地址: 一个著名的日志系统是怎么设计出来的 然后说一下,为啥 ...