为什么Java中“1000==1000”为false,而”100==100“为true?

大家好,我是可乐。

在日常编程中,我们经常遇到一些看似简单却隐藏着复杂逻辑的问题。

比如,你是否想过为什么在 Java 中表达式1000==1000会返回 false,而 100==100 却返回 true 呢?

ini 复制代码
 Integer a = 100;
 Integer b = 100;
 System.out.println(a == b); // 输出:true
 ​
 Integer c = 1000;
 Integer d = 1000;
 System.out.println(c == d); // 输出:false

1、源码追溯

解决问题,一定要深入本质,而解决编程问题,深入本质的方法就是对源码一探究竟。

可能大家不知道 Integer a = 100 这种代码是看哪个源码,不要紧,我们可以看下其编译后的 class 文件。

很明显,我们得看 Integer 类的 valueOf 方法:

继续看 IntegerCache :

为了防止大家不好理解,我这里为这个方法添加了详细注释:

java 复制代码
 private static class IntegerCache {
     // 缓存的下界值,固定为-128
     static final int low = -128;
 ​
     // 缓存的上界值,可以通过系统属性进行配置
     static final int high;
 ​
     // 缓存数组,用于存储从low到high范围内的Integer对象
     static final Integer cache[];
 ​
     static {
         // 默认情况下,缓存的上界是127
         int h = 127;
 ​
         // 尝试从系统属性java.lang.Integer.IntegerCache.high中获取自定义的上界值
         String integerCacheHighPropValue =
             sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
         if (integerCacheHighPropValue != null) {
             try {
                 // 将字符串转换为整数
                 int i = parseInt(integerCacheHighPropValue);
                 // 确保自定义的上界至少为127,以包含Java规范要求的缓存范围
                 i = Math.max(i, 127);
                 // 确保上界不超过Integer.MAX_VALUE - (-low) - 1,以防止数组大小超出Integer的最大值
                 h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
             } catch( NumberFormatException nfe) {
                 // 如果字符串无法解析为整数,忽略该属性并保持默认的上界值
             }
         }
         // 设置高界值
         high = h;
 ​
         // 初始化缓存数组,数组大小根据low和high计算得出
         cache = new Integer[(high - low) + 1];
         int j = low;
         for(int k = 0; k < cache.length; k++) {
             // 创建Integer对象并填充数组
             cache[k] = new Integer(j++);
         }
 ​
         // 断言确保缓存的上界至少为127,符合Java语言规范
         assert IntegerCache.high >= 127;
     }
 ​
     // 私有构造器,防止外部实例化这个内部类
     private IntegerCache() {}
 }

2、源码解读

其实这部分源码不难理解,首先对于 valueOf 方法,当传入的整型值在 -128-127 之间时,返回的是 IntegerCache 里面的值。

这个 IntegerCache 是在 Java 的 Integer 类中的一个内部静态类 ,它缓存了 -128 到 127 之间的整数。

当我们声明一个 Integer 对象并赋予一个在这个范围内的值时,Java 实际上会返回一个预先创建好的对象引用。

这种机制可以有效减少内存的使用,并提高性能。

3、解答问题

看懂了源码,在回到上面的问题,为什么表达式1000==1000会返回 false,而 100==100 却返回 true 呢?

当我们使用 Integer 对象比较两个数时,实际上是在比较对象的内存地址。由于"100"在缓存范围内,两个"100"实际上引用的是同一个对象,所以返回 true。

相反,"1000"不在缓存范围内,即使数值相同,两个"1000"也是不同的对象,因此内存地址不同,返回 false。

4、正确比较

其实对于 Integer 这种包装类比较大小,我们应该使用 equals() 方法来比较两个 Integer 对象的数值,而不是直接使用 == 操作符,除非我们确实想比较对象的引用。

ini 复制代码
 Integer a = 100;
 Integer b = 100;
 System.out.println(a.equals(b)); // 输出:true
 ​
 Integer c = 1000;
 Integer d = 1000;
 System.out.println(c.equals(d)); // 输出:true

这点在阿里开发手册中也有详细说明:

如果你是一名Java开发人员,我还是比较推荐你去阅读这个手册,对我们日常编码规范还是挺有帮助的。

这个手册我这里也给大家整理好了,而且是最新版的.

下载地址:pan.quark.cn/s/30d2c2c42...

相关推荐
哎呦没29 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch1 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
编程、小哥哥1 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
IT学长编程2 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇2 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码2 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries3 小时前
读《show your work》的一点感悟
后端
郭二哈3 小时前
C++——模板进阶、继承
java·服务器·c++
A尘埃3 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23073 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端