为什么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...

相关推荐
檀越剑指大厂17 分钟前
【Java基础】使用Apache POI和Spring Boot实现Excel文件上传和解析功能
java·spring boot·apache
苹果酱056721 分钟前
Golang的网络流量分配策略
java·spring boot·毕业设计·layui·课程设计
小青柑-23 分钟前
Go语言中的接收器(Receiver)详解
开发语言·后端·golang
孑么1 小时前
GDPU Android移动应用 重点习题集
android·xml·java·okhttp·kotlin·android studio·webview
未命名冀2 小时前
微服务面试相关
java·微服务·面试
Heavydrink2 小时前
ajax与json
java·ajax·json
阿智智2 小时前
纯手工(不基于maven的pom.xml、Web容器)连接MySQL数据库的详细过程(Java Web学习笔记)
java·mysql数据库·纯手工连接
fangxiang20082 小时前
spring boot 集成 knife4j
java·spring boot
C++小厨神2 小时前
Bash语言的计算机基础
开发语言·后端·golang
BinaryBardC2 小时前
Bash语言的软件工程
开发语言·后端·golang