程序员老鬼

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

嗨,我是东哥!作为一个程序员,我每天都在和代码打交道,而有时候代码里的一些小坑总能给我们带来意想不到的惊喜和困惑。
今天我就给大家聊聊一个经典的Java面试题:为什么在Java中,1000==1000是false,而100==100却是true?
这看起来挺魔幻的吧?别急,我们一步一步来揭开这背后的奥秘。
首先,咱们来看一段简单的代码:
Integer a = 1000, b = 1000;  System.out.println(a == b); // 输出:false
Integer c = 100, d = 100; System.out.println(c == d); // 输出:true
咱们的第一个问题自然就是:为什么第一个输出是false,而第二个却是true?🤔

# 基本知识复习

在Java中,==操作符比较的是两个对象的引用,也就是说,==判断的是两个引用是否指向同一个对象。
换句话说,如果两个Integer对象的引用指向的是同一个内存地址,那么==就会返回true。如果它们指向的是不同的内存地址,即使它们的值相同,==也会返回false。
说到这儿,大家可能会觉得,第一个比较的结果应该是false,那第二个比较也应该是false才对啊!
然而事实并非如此,这其中就牵扯到了Java中的一个隐藏机制——Integer Cache。

# Integer Cache机制

Java的Integer类中有一个私有静态内部类叫做IntegerCache,它负责缓存从-128到127之间的所有Integer对象。
也就是说,在这个范围内的整数是被缓存起来的,每次我们创建一个这样的Integer对象时,Java会直接返回缓存中的实例,而不是创建一个新的对象。
简单来说,当我们执行以下代码时:
Integer c = 100;Integer d = 100;
Java实际上是在内部做了这样的处理:
Integer c = Integer.valueOf(100);Integer d = Integer.valueOf(100);
在Integer.valueOf()方法中,Java会先检查这个数字是否在-128到127之间,如果是,它就会从IntegerCache中取出已经缓存的对象。这个时候,c和d就指向了同一个对象,所以c == d返回true。
来看下Integer.valueOf()的代码实现:
public static Integer valueOf(int i) {    if (i >= IntegerCache.low && i <= IntegerCache.high) {        return IntegerCache.cache[i + (-IntegerCache.low)];    }    return new Integer(i);}
看到这里,大家应该已经明白了吧。当我们用Integer c = 100;时,实际上Java返回的是IntegerCache中的一个已经缓存的Integer对象。
而当我们用Integer a = 1000;时,因为1000超出了IntegerCache的范围,所以Java为a和b分别创建了新的Integer对象,因此a == b返回false。

# 为什么要有Integer Cache?

那有人可能会问了:Java为啥要搞这个缓存机制呢?这就得从性能优化的角度说起了。📈
在实际应用中,-128到127这个范围的整数使用频率特别高,比如循环变量、数组索引等等。如果每次创建这样的整数都需要分配新的内存,那就太浪费资源了。而缓存这些常用的小整数可以显著减少内存分配,提升性能。
不过这也提醒了我们,在使用Integer进行比较时,要特别注意对象的引用,尽量避免使用==去判断Integer的值是否相等,而应该使用equals()方法来进行比较。

# 反射API的奇妙操作

聊到这里,我再给大家展示一个有趣的例子——如何通过反射API来玩转这个IntegerCache机制。这个例子不建议在生产环境中使用,但作为一名程序员,咱们总是喜欢搞点好玩的东西嘛~😏
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {    Class<?> cacheClass = Integer.class.getDeclaredClasses()[0]; // 获取IntegerCache类    Field cacheField = cacheClass.getDeclaredField("cache"); // 获取cache字段    cacheField.setAccessible(true); // 设置字段可访问
Integer[] newCache = (Integer[]) cacheField.get(cacheClass); // 获取cache数组 newCache[132] = newCache[133]; // 修改缓存
int a = 2; int b = a + a; System.out.printf("%d + %d = %d", a, a, b); // 输出:2 + 2 = 5}
这段代码做了什么呢?简单说,它通过反射直接修改了IntegerCache的内容,将132这个位置的值设置成了133的值。于是,当我们运行2 + 2时,竟然得到了一个奇怪的结果——5!😂
虽然这个例子很有趣,但也提醒我们,在Java中,使用反射可以带来很大的灵活性,但同时也可能带来一些不可预测的结果。所以,反射API是把双刃剑,大家使用时一定要谨慎啊!

# 结语

总之,Java中的Integer比较看似简单,实际上却藏着不少玄机。
作为一名程序员,我们不仅要掌握这些底层机制,更要学会在实际开发中合理运用这些知识。
希望今天的分享能让你对Java中的==有一个更深入的理解,也希望大家在写代码时能够少踩坑,多写出优雅的代码!💻

最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek

也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。

-END-

ok,今天先说到这,老规矩,给大家分享一份不错的副业资料,感兴趣的同学可以链接我,微信:hls404 找我领取。

以上,就是今天的分享了,看完文章记得右下角点赞,也欢迎在评论区写下你的留言。