为什么==与Integer.valueOf(String)比较给127和128不同的结果?

我不知道为什么这些代码行返回不同的值:

System.out.println(Integer.valueOf("127")==Integer.valueOf("127")); System.out.println(Integer.valueOf("128")==Integer.valueOf("128")); System.out.println(Integer.parseInt("128")==Integer.valueOf("128")); 

输出是:

 true false true 

为什么第一个返回true ,第二个返回false ? 有什么不同之处,我不知道127128之间? (当然我知道127 < 128

另外,为什么第三个返回true

我已经阅读了这个问题的答案,但我仍然没有得到它如何返回true ,以及为什么第二行代码返回false

这里有一个惊人的区别。

valueOf返回一个Integer对象,它的值可能在-128到127之间caching。这就是为什么第一个值返回true – 它被caching了 – 第二个值返回false – 128不是一个caching值,所以你获得两个独立的Integer实例。

请注意 ,您正在比较引用和Integer#valueOf ,并且如果比较的值大于caching支持的值,则即使parsing的值是等价的,也不会计算为true (例如: Integer.valueOf(128) == Integer.valueOf(128) )。 您必须使用equals()

parseInt返回一个原始的int 。 这就是为什么第三个值返回true128 == 128被评估,当然是true

现在,第三个结果是true

  • 相对于您正在使用的等价操作符以及您具有的数据types(即intInteger , 发生拆箱转换 。 当然,你会从右侧获得一个Integer

  • 转换之后,您正在比较两个原始的int值。 如你所期望的那样,比较会发生在原始数据上,所以你比较128128

Integer类有一个静态caching,可以存储256个特殊的Integer对象,每个对象的值在-128到127之间。考虑到这一点,请考虑这三者之间的区别。

 new Integer(123); 

这(显然)是一个全新的Integer对象。

 Integer.parseInt("123"); 

这在parsingString之后返回一个int原始值。

 Integer.valueOf("123"); 

这比其他的更复杂。 它从parsingString 。 然后,如果该值在-128和127之间,则从静态caching中返回相应的对象。 如果该值超出此范围,则调用new Integer()并传递该值,以便获得新的对象。

现在,考虑这个问题中的三个expression式。

 Integer.valueOf("127")==Integer.valueOf("127"); 

这将返回true,因为值为127的Integer从静态caching中检索两次,并与自身进行比较。 只涉及一个Integer对象,所以这返回true

 Integer.valueOf("128")==Integer.valueOf("128"); 

这将返回false ,因为128不在静态caching中。 因此,为平等的每一方创build一个新的Integer 。 由于存在两个不同的Integer对象,并且==对象只在双方是完全相同的对象时才返回true ,所以这将是false

 Integer.parseInt("128")==Integer.valueOf("128"); 

这是比较左侧的基本int值128和右侧新创build的Integer对象。 但是因为把一个int和一个Integer比较是没有意义的,所以Java在比较之前会自动取消Integer 。 所以你最终将一个int与一个int进行比较。 由于基元128等于自身,所以这返回true

注意从这些方法返回的值。 valueOf方法返回Integer实例:

 public static Integer valueOf(int i) 

parseInt方法返回整数值(原始types):

 public static int parseInt(String s) throws NumberFormatException 

比较说明:

为了节省内存,包装对象的两个实例在它们的基本值相同时总是==:

  • 布尔
  • 字节
  • 从\ u0000到\ u007f的字符(7f是十进制的127)
  • 短和整数从-128到127

当==用于比较一个基元到一个包装器时,包装器将被解包,比较将是原始的。

在你的情况下(根据上述规则):

 Integer.valueOf("127")==Integer.valueOf("127") 

这个expresion比较了对同一个对象的引用,因为它包含-128到127之间的Integer值,所以它返回true。

 Integer.valueOf("128")==Integer.valueOf("128") 

此expression式比较对不同对象的引用,因为它们包含的Integer值不在<-128,127>中,所以它返回false。

 Integer.parseInt("128")==Integer.valueOf("128") 

这个expression式比较原始值(左边)和对象(右边)的引用,所以右边将被解开,并且他的原始types将与左边的比较,所以它返回true。

为了补充给出的答案,还要注意以下几点:

 public class Test { public static void main(String... args) { Integer a = new Integer(129); Integer b = new Integer(129); System.out.println(a == b); } } 

这段代码也会打印: false

正如用户杰伊在接受的答案的评论中声称,在对象上使用operator ==时必须小心,在这里你检查两个引用是否相同,不是,因为它们是不同的objets,虽然它们表示同样的价值。 要比较对象,应该使用equals方法:

 Integer a = new Integer(128); Integer b = new Integer(128); System.out.println(a.equals(b)); 

这将打印: true

你可能会问, 但是为什么第一行打印是true 。 检查Integer.valueOf方法的源代码,可以看到以下内容:

 public static Integer valueOf(String s) throws NumberFormatException { return Integer.valueOf(parseInt(s, 10)); } public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } 

如果param是IntegerCache.low (默认为-128)和IntegerCache.high (在运行时用最小值127计算)之间的整数,则返回预分配(caching)的对象。 所以当你使用127作为参数的时候,你会得到两个对同一个caching对象的引用,并且在引用的比较中变为true

整数对象caching在256 Integer的-128到127之间

您不应该将对象引用与==!=进行比较。 你应该使用。 等于(..) ,或者更好 – 使用原始的int而不是Integer。

parseInt :将string参数parsing为带符号的十进制整数。 string中的字符必须全部为十进制数字,但第一个字符可能是ASCII减号' – '('\ u002D')以指示负值。 得到的整数值被返回,就好像参数和基数10被作为parseInt(java.lang.String,int)方法的参数给出一样。

valueOf返回一个Integer对象,当使用第二个参数给定的基数进行分析时,该对象保存从指定String中提取的值。 第一个参数被解释为表示由第二个参数指定的基数中的有符号整数,就好像参数被赋予parseInt(java.lang.String,int)方法一样。 结果是一个Integer对象,它表示由string指定的整数值。

相当于

 new Integer(Integer.parseInt(s, radix)) 

基数 – 用于解释的基数

所以如果你等于整数inbetween的Integer.valueOf()

-128到127它在你的情况下返回true

lesser than -128且greater than 127时,它给出false