为什么==与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
? 有什么不同之处,我不知道127
和128
之间? (当然我知道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
。 这就是为什么第三个值返回true
– 128 == 128
被评估,当然是true
。
现在,第三个结果是true
:
-
相对于您正在使用的等价操作符以及您具有的数据types(即
int
和Integer
, 发生拆箱转换 。 当然,你会从右侧获得一个Integer
。 -
转换之后,您正在比较两个原始的
int
值。 如你所期望的那样,比较会发生在原始数据上,所以你比较128
和128
。
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