java 100==100,为什么Java中100==100为true而1000==1000为false?详细分析解释

这可能是每一个初学Java的人都会遇到的很有意思的问题。

执行下列代码:Integer a = 100;

Integer b = 100;

Integer c = 1000;

Integer d = 1000;

System.out.println(a==b);

System.out.println(c==d);

你将会得到以下的结果:true

false

那么这是为什么呢?

这里我们就不得不提一下“==”的作用了(更多详情请点击链接了解):我们都知道,“==”是用来比较两个变量是否相等,但是在具体应用中,基本类型和引用类型是要分开来讨论的,基本类型,如int、double、char等,使用“==”仅判断值是否相等,但是引用类型,如类和装箱值类型等,则比较的是两个变量引用的是否为同一个对象。

所以,看到这里,就应该可以理解为什么“c==d”返回的是false了,因为c和d是独立的两个对象。

等等!你是不是又有了新的疑问?为什么a==b返回的却是true呢?这不科学!很好,研究问题就是要将问题理解得足够透彻,要学会刨根问底,小伙子我看好你!

要弄清这个问题,我们可以打开Integer类的实现代码一探究竟(按住Ctrl鼠标左键点击Integer关键字即可打开实现代码)。下翻到代码约780行左右(jdk1.8)我们可以看到一个叫做“IntegerCache”的内部私有类,它缓存了从-128到127之间的所有的整数对象。

实际上,只有基本类型才支持直接赋值操作,而引用类型是需要使用“new”关键字来进行创建的,比如:int a = 0;//基本类型

Integer b = new Integer(10);//引用类型

但是,就如我们所使用的上述代码:Integer a = 100;

Integer b = 100;

Integer c = 1000;

Integer d = 1000;

为什么也能正常执行呢?

原来,是Java编译器在内部为我们进行了转换,自动调用了Integer类的“valueOf()”方法,当我们声明:Integer a = 100;

的时候,实际上执行的代码是:Integer i = Integer.valueOf(100);

不妨让我们来做个小实验:Integer a = 100;

Integer b = 100;

Integer c = 1000;

Integer d = 1000;

Integer e = Integer.valueOf(100);

Integer f = Integer.valueOf(1000);

System.out.println(a==b);

System.out.println(c==d);

System.out.println(a==e);

System.out.println(c==f);

输出结果为:true

false

true

false

显然,和直接使用“=”定义得出的结果一致,可见我们的推理是正确的。

现在,让我们就来一起了解一下“valueOf()”函数的真面目:public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

可见,当赋值为“IntegerCache”中已经缓存的数字时,即-128~+127,Java将从高速缓存返回实例。

所以当我们执行:Integer a = 100;

Integer b = 100;

时,Java并不会重新创建对象,而是直接将高速缓存中的对象直接赋给a与b,即a与b指向同一个对象,所以“a==b”返回了“true”。你明白了吗?

有的朋友看到这里可能又要问了:为什么这里需要缓存?所有的数字统一处理多好?

一种比较合理的解释是,在此范围内的“小”整数比“大”整数的使用率要高,因此,使用相同的底层对象是有价值的,可以减少潜在的内存占用并提高执行效率。

那么,下面的代码的输出结果是什么呢?Integer a = 100;

Integer g = new Integer(100);

Integer h = new Integer(100);

System.out.println(a==g);

System.out.println(g==h);

哈哈,会不会有点头晕了呢?输出结果是:false

false

直接new出来的当然是两个不同的对象啦,这里就不用再考虑高速缓存的问题了~

好了,本篇博客到此就要结束了,我们下篇再见。

行文参考:参考地址

挖坑时间:

然而,通过反射API你会误用此功能。运行下面的代码,享受它的魅力吧:public static void main(String[] args) {

doSomethingMagic();

int a = 2;

int b = a + a;

System.out.printf("%d + %d = %d", a, a, b); // 2 + 2 = 5

}

public static void doSomethingMagic() {

Class> cache = Integer.class.getDeclaredClasses()[0]; // 1

Field myCache;

try {

myCache = cache.getDeclaredField("cache"); // 2

myCache.setAccessible(true);// 3

Integer[] newCache = (Integer[]) myCache.get(cache); // 4

newCache[132] = newCache[133]; // 5

} catch (NoSuchFieldException | IllegalAccessException e) {

e.printStackTrace();

}

}

全文完。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值