奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?
2017-11-23 12:49
316 查看
奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?
这是我们今天要讨论的话题,因为我觉得它非常的有趣。
如果你运行如下代码:
2
3
4
5
6
7
8
9
10
你会得到如下结果:
2
我们知道,如果两个引用指向同一个对象,那么==就成立;反之,如果两个引用指向的不是同一个对象,那么==就不成立,即便两个引用的内容是一样的。因此,结果就会出现false。
这是非常有趣的地方。如果你查看Integer.java类,你会找到IntegerCache.java这个内部私有类,它为-128到127之间的所有整数对象提供缓存。
这个东西为那些数值比较小的整数提供内部缓存,当进行如此声明时:
它的内部就是这样的:
其实我通过将
如果我们观察valueOf()类函数,我们可以看到:
2
3
4
5
通过看源码能够知道,整数类型在-128~127之间时,会使用缓存,造成的效果就是,如果已经创建了一个相同的整数,使用valueOf创建第二次时,不会使用new关键字,而用已经缓存的对象。所以使用valueOf方法创建两次对象,若对应的数值相同,且数值在-128~127之间时,两个对象都指向同一个地址。
因此。。。
两者指向同样的对象。
这就是为什么下面这段代码的结果为true了:
现在你可能会问,为什么会为-128到127之间的所有整数设置缓存?
这是因为在这个范围内的小数值整数在日常生活中的使用频率要比其它的大得多,多次使用相同的底层对象这一特性可以通过该设置进行有效的内存优化。你可以使用reflection API任意使用这个功能。
运行下面的这段代码,你就会明白它的神奇所在了。
2
3
4
5
6
7
8
9
10
11
12
13
打印结果竟然是:
2
我们再次看一下反汇编代码:
是不是又和上面的是同一个问题呢?
但是结果为什么是
我们继续去看一下 Integer 源码,去深入了解 Integer 缓存机制,下面截个图:
根据源码可以发现最后修改 Integer 缓存上限时候的方法有点小瑕疵。我们看看Api给我们怎么建议的一段话:
原来我们只需要:运行时设置
这是我们今天要讨论的话题,因为我觉得它非常的有趣。
如果你运行如下代码:
class A { public static void main(String[] args) { Integer a = 128, b = 128; System.out.println(a == b); Integer c = 127, d = 127; System.out.println(c == d); } }1
2
3
4
5
6
7
8
9
10
你会得到如下结果:
false true1
2
我们知道,如果两个引用指向同一个对象,那么==就成立;反之,如果两个引用指向的不是同一个对象,那么==就不成立,即便两个引用的内容是一样的。因此,结果就会出现false。
这是非常有趣的地方。如果你查看Integer.java类,你会找到IntegerCache.java这个内部私有类,它为-128到127之间的所有整数对象提供缓存。
这个东西为那些数值比较小的整数提供内部缓存,当进行如此声明时:
Integer c = 1271
它的内部就是这样的:
Integer var3 = Integer.valueOf(127);1
其实我通过将
A.class文件反编译后,代码如下图:
如果我们观察valueOf()类函数,我们可以看到:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }1
2
3
4
5
通过看源码能够知道,整数类型在-128~127之间时,会使用缓存,造成的效果就是,如果已经创建了一个相同的整数,使用valueOf创建第二次时,不会使用new关键字,而用已经缓存的对象。所以使用valueOf方法创建两次对象,若对应的数值相同,且数值在-128~127之间时,两个对象都指向同一个地址。
因此。。。
Integer c = 127, d = 127;1
两者指向同样的对象。
这就是为什么下面这段代码的结果为true了:
System.out.println(c == d);1
现在你可能会问,为什么会为-128到127之间的所有整数设置缓存?
这是因为在这个范围内的小数值整数在日常生活中的使用频率要比其它的大得多,多次使用相同的底层对象这一特性可以通过该设置进行有效的内存优化。你可以使用reflection API任意使用这个功能。
运行下面的这段代码,你就会明白它的神奇所在了。
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Class cache = Integer.class.getDeclaredClasses()[0]; Field myCache = cache.getDeclaredField("cache"); myCache.setAccessible(true); Integer[] newCache = (Integer[]) myCache.get(cache); newCache[132] = newCache[133]; int a = 2; int b = a + a; System.out.printf("%d + %d = %d", a, a, b); // }1
2
3
4
5
6
7
8
9
10
11
12
13
打印结果竟然是:
2 + 2 = 51
2
我们再次看一下反汇编代码:
是不是又和上面的是同一个问题呢?
但是结果为什么是
2 + 2 = 5呢?
我们继续去看一下 Integer 源码,去深入了解 Integer 缓存机制,下面截个图:
根据源码可以发现最后修改 Integer 缓存上限时候的方法有点小瑕疵。我们看看Api给我们怎么建议的一段话:
the size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.1
原来我们只需要:运行时设置
-XX:AutoBoxCacheMax=133就OK。
相关文章推荐
- 奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 为什么128 == 128返回为False,而127 == 127会返回为True?
- (转)奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- java常量池概念 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
- [转载] 在java中为什么变量1000 = 1000 返回false,但是100=100返回true?
- 【译】在Java中,为什么1000 == 1000 返回false,而100 == 100 返回true?
- 128==128返回false,127==127返回true ??
- 为什么在 Java 中1000==1000返回false,而100==100返回true呢?
- Java为什么两个值相等的对象==比较返回false而两个值相等的不同类型的的基本数据类型返回true
- java中byte取值范围为什么是 -128到127
- java中为什么byte的取值范围是-128到+127