为什么在 Java 中1000==1000返回false,而100==100返回true呢?

英文原文:
https://dzone.com/articles/why-1000-1000-returns-false-but-100-100-returns-tr

亦枫译文:
http://www.jianshu.com/p/877f0a8a9607

《为什么在 Java 中1000==1000返回false,而100==100返回true呢?》 Java.jpg

这是一个非常有意思并且值得讨论的话题。

如果你运行下面的代码:

Integer a = 1000, b = 1000; 
System.out.println(a == b);//1
Integer c = 100, d = 100; 
System.out.println(c == d);//2

你将得到这样的结果:

fasle
true

先了解一下基础知识:我们知道,如果两个引用指向相同的对象,它们在 == 表达式中是相等的;如果两个引用指向不同的对象,尽管它们拥有相同的内容即值,在 == 表达式中也是不相等的。

所以,按道理,上面第二条语句也应该返回 false 。

这就是它有意思的地方了。如果你去翻阅 Java 源代码,查看 Integer.java 类的话,你会发现在这个类里面有一个内部私有类 —— IntegerCache.java ,这个内部私有类缓存了数值为 -128 到 127 之间所有的整型对象。

那么原理就搞清楚了,所有的小整数都被缓存到内部,然后当我们类似这样定义的时候 ——

Integer c = 100;

它在内部做了如下处理:

Integer i = Integer.valueOf(100);

如果我们继续翻阅 valueOf() 的源代码,将会看到 ——

 public static Integer valueOf(int i) {    
        return  i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
}

如果数值处于 -128 到 127 之间,它将返回缓存中的实例。

所以…

Integer c = 100, d = 100;

从根本上来讲,指向了相同的对象。

这就是为什么如果我们这样写:

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

将得到 true 。

现在也许你会问,为什么这里需要缓存?

从逻辑基础上来讲,处于这个范围的小整数比大整数要使用的多,所以,对于减少潜在的内存占用,使用相同的底层对象更有价值。

然而,通过使用反射API,你可能会滥用这个功能。

运行下面一段代码,并且享受它的魅力吧

public static void main(String[] args) throws  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

    Class cache = Integer.class.getDeclaredClasses()[0]; //1
    Field myCache = cache.getDeclaredField("cache"); //2
    myCache.setAccessible(true);//3

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

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

 }
    原文作者:亦枫
    原文地址: https://www.jianshu.com/p/877f0a8a9607
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞