奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?

这是我们今天要讨论的话题,因为我觉得它非常的有趣。

如果你运行如下代码:


  1. class  A 
  2.     public static void main(String[] args)  
  3.     { 
  4.         Integer a = 128, b = 128; 
  5.         System.out.println(a == b); 
  6.         Integer c = 127, d = 127; 
  7.         System.out.println(c == d); 
  8.     } 
  9. }  

你会得到如下结果:


  1. false 
  2. true  

我们知道,如果两个引用指向同一个对象,那么==就成立;反之,如果两个引用指向的不是同一个对象,那么==就不成立,即便两个引用的内容是一样的。因此,结果就会出现false。

这是非常有趣的地方。如果你查看Integer.Java类,你会找到IntegerCache.java这个内部私有类,它为-128到127之间的所有整数对象提供缓存。

这个东西为那些数值比较小的整数提供内部缓存,当进行如此声明时:


  1. Integer c = 127 

它的内部就是这样的:


  1. Integer var3 = Integer.valueOf(127); 

其实我通过将A.class文件反编译后,代码如下图:

如果我们观察valueOf()类函数,我们可以看到:


  1. public static Integer valueOf(int i) { 
  2.         if (i >= IntegerCache.low && i <= IntegerCache.high) 
  3.             return IntegerCache.cache[i + (-IntegerCache.low)]; 
  4.         return new Integer(i); 
  5.     }  

如果值在-128到127之间,它就会返回该缓存的实例。

因此。。。


  1. Integer c = 127, d = 127; 

两者指向同样的对象。

这就是为什么下面这段代码的结果为true了:


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

现在你可能会问,为什么会为-128到127之间的所有整数设置缓存?

这是因为在这个范围内的小数值整数在日常生活中的使用频率要比其它的大得多,多次使用相同的底层对象这一特性可以通过该设置进行有效的内存优化。你可以使用reflection API任意使用这个功能。

运行下面的这段代码,你就会明白它的神奇所在了。


  1. public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 
  2.  
  3.       Class cache = Integer.class.getDeclaredClasses()[0];  
  4.       Field myCache = cache.getDeclaredField("cache"); 
  5.       myCache.setAccessible(true); 
  6.  
  7.       Integer[] newCache = (Integer[]) myCache.get(cache);  
  8.       newCache[132] = newCache[133];  
  9.  
  10.       int a = 2; 
  11.       int b = a + a; 
  12.       System.out.printf("%d + %d = %d", a, a, b); // 
  13.     }  

打印结果竟然是:


  1. 2 + 2 = 5  

我们再次看一下反汇编代码:

是不是又和上面的是同一个问题呢?

但是结果为什么是 2 + 2 = 5 呢?

我们继续去看一下 Integer 源码,去深入了解 Integer 缓存机制,下面截个图:

根据源码可以发现最后修改 Integer 缓存上限时候的方法有点小瑕疵。我们看看Api给我们怎么建议的一段话:


  1. the size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. 

原来我们只需要:运行时设置 -XX:AutoBoxCacheMax=133 就OK。

本文作者:佚名

来源:51CTO

时间: 2024-08-26 15:46:15

奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?的相关文章

java类的问题-java题,将该字符串每个字符与&amp;amp;#39;U&amp;amp;#39;之差的绝对值的升序排序

问题描述 java题,将该字符串每个字符与'U'之差的绝对值的升序排序 输入一组字符串,将该字符串每个字符与'U'之差的绝对值的升序排序.在线等!!? 解决方案 每个字符都减去同一个字符跟不减不一样么?没有必要啊.直接排序即可. 解决方案二: 首先,按照我的一贯观点,这种问题和编程语言无关,和编程语言无关,和编程语言无关.重要的事情说三遍! 设计重点:1.与U的差值存储;2.升序排序. 已知的排序算法相当多,不过在本问题情形下,需要稍作变通. 给出一个简单方案吧:给定字符串Char[];比较差值

java题,如何将数组中的数据格式化输出?(有代码)

问题描述 java题,如何将数组中的数据格式化输出?(有代码) 例如这串代码 import java.util.*; class gongzi{ public static void main(String[] args){ Scanner kb=new Scanner(System.in); int n=kb.nextInt(); int i; String k=""; for(i=0;i<n;i++){ String name=kb.next(); String f=name

java 接口 接口实现-Java中一个类如何实现多个接口中同名同参返回值不同的方法?

问题描述 Java中一个类如何实现多个接口中同名同参返回值不同的方法? 如:` class A implements Interface1,Interface2{ //这里该怎么写呢? } interface Interface1{ public void method(); } interface Interface2{ public int method(); } 解决方案 class A implements Interface1,Interface2{ //直接写啊 public voi

Java模拟HTTP请求如何获取请求页面中ajax方法的返回值

问题描述 Java模拟HTTP请求如何获取请求页面中ajax方法的返回值 我有一个AAA.JSP页面是通过加载百度的地图API的JS文件,再调用其中的ajax请求方法获取地理坐标.地理坐标在该ajax方法的返回参数中的.我现在需要在服务器端获取地理位置信息,因此我通过java程序模拟HTTP请求,去访问AAA.JSP,但因为ajax是异步的,模拟程序访问该页面的时候,其中的ajax方法还没执行结束,服务器就返回了该页面的静态HTML内容,导致我无法获取地理位置信息.请问如何让服务器端在ajax执

关于java数组定义一个函数清除该数组的重复元素,返回一个不能浪费长度的数组.

问题描述 关于java数组定义一个函数清除该数组的重复元素,返回一个不能浪费长度的数组. package cn.xtgj.testarr; /** 目前有数组" int[] arr = {11,2, 4, 2, 10, 11},定义一个函数清除该数组的重复元素,返回一个不能浪费长度的数组. * */ public class Arr { public void method(int[] arr){ int count=0; for(int i=0;i<arr.length;i++){ fo

大小写-java题,大神帮忙给个思路

问题描述 java题,大神帮忙给个思路 请用java描述一种算法,可以判断两个类型为String的英文意思相同,其中意思相同的主要含义是: 1,与大小写无关! 2,与句中标点符号无关 3,句子中多个空格和单个空格等价 解决方案 你先用String.trim();去掉空格,然后用replace("标点符号","");去掉标点符号,最后用string.equals(string); 应该可以吧. 解决方案二: 都是调用String对象的api,一种是上面说的,但最后的比

java中字符串转换为字节数组请问用什么方法,字符串返回字节数组怎么做?

问题描述 java中字符串转换为字节数组请问用什么方法,字符串返回字节数组怎么做? java中字符串转换为字节数组请问用什么方法,字符串返回字节数组怎么做? 解决方案 http://blog.csdn.net/shuaihj/article/details/7478773http://blog.csdn.net/abin_gha/article/details/6317850 解决方案二: java中String类有getBytes方法,可以将字符串转成字节数组.字节数组可以直接写入到输出流中,

java题求思路,刚学的数组

问题描述 java题求思路,刚学的数组 有5个班,现在要分别统计这5个班的学生的平均薪资,然后统计整体的平均薪资, 再按照性别在分别统计每个班男女的平均薪资, 然后按照每个班的平均薪资由高到低输出每一个班的每一个学生的薪资.性别和名字. 解决方案 Java小计算器~刚学 解决方案二: 这题目不难啊,就几个FOR循环,加减乘除操作就完了 import java.util.Scanner; public class Method { public static void main(String[]

请推荐比较好的Java题库

问题描述 谁能推荐一下比较好的能下载的Java题库 解决方案 解决方案二:目的是什么解决方案三:准备面试解决方案四:如果面试,到网上搜,很多面试题.解决方案五:Java面试宝典2010版,百度文库里有.内容很多,建议楼主选择一些常用的重点来学习.其实网上面试题目一大堆,除了做题目之外,还要注重一些面试技巧,这也比较重要.