写点什么

Integer.valueOf(String) 方法之惑

作者:Steven
  • 2023-01-11
    河南
  • 本文字数:1622 字

    阅读完需:约 5 分钟

有个兄台在 StackOverflow 上发起了一个问题,是这么问的:


“ 我被下面的代码搞晕了,为什么它们会返回不同的值?”


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。


回答 #1:


Integer.valueOf(String)确有一个不同寻常的行为。


valueOf 会返回一个 Integer(整型)对象,当被处理的字符串在-128 和 127(包含边界)之间时,返回的对象是预先缓存的。这就是为什么第一行的调用会返回 true-127 这个整型对象是被缓存的(所以两次 valueOf 返回的是同一个对象)——第二行的调用返回 false 是因为 128 没有被缓存,所以每次调用,都会生成一个新的整型对象,因此两个 128 整型对象是不同的对象。


重要的是你要知道在上面的比较中,你实际进行比较的是 integer.valueOf 返回的对象引用,所以当你比较缓存外的整型对象时,相等的判断不会返回 true,就算你传个 valueOf 的值是相等的也没用。(就像第二行中 Integer.valueOf(128)==Integer.valueOf(128))。想让这个判断返回 true,你需要使用 equals()方法。


parseInt()返回的不是整型对象,而是一个 int 型基础元素。这就是为什么最后一个判断会返回 true,第三行的判断中,在判断相等时,实际比较的是 128 == 128,所以它必然是相等的。


再来说说第三种比较中的一点区别,使得它的结果与第二种比较不一样了:


一个 unboxing conversion(一种比较时的转换,把对对象的引用转换为其对应的原子类型)在第三行的比较中发生了。因为比较操作符使用了==同时等号的两边存在一个 int 型和一个 Integer 对象的引用。这样的话,等号右边返回的 Integer 对象被进一步转换成了 int 数值,才与左边进行相等判断。


所以在转换完成后,你实际比较的是两个原子整型数值。这种转换正是你在比较两个原子类型时所期待看到的那样,所以你最终比较了 128 等于 128。


回答 #2:


Integer 类有一个静态缓存,存储了 256 个特殊的 Integer 对象——每个对象分别对应-128 和 127 之间的一个值。


有了这个概念,就可以知道上面三行代码之间的区别。


new Integer(123);


显示创建了一个新的 Integer 对象。


Integer.parseInt("123");


解析完字符串后返回一个 int 值。


Integer.valueOf("123");


这种情况比其他的要更复杂一些。首先进行了字符串解析,然后如果解析的值位于-128 和 127 之间,就会从静态缓存中返回对象。如果超出了这个范围,就会调用 Integer()方法并将解析的值作为参数传入,得到一个新的对象。


现在,让我们看一下问题中的 3 个表达式。


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


上面的表达式返回 true,因为 Integer 的值从静态缓存中取了 2 次,表达式返回了对象与自己比较的结果。因为只有一个 Integer 对象,所以返回结果为 true。


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


上面的表达式返回 false,因为 128 没有存在静态缓冲区。所以每次在判断相等时等式两边都会创建新的 Integer 对象。由于两个 Integer 对象不同,所以==只有等式两边代表同一个对象时才会返回 true。因此,上面的等式返回 false。


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


上面的表达式比较的是左边的原始 int 值 128 与右边新创建的 Integer 对象。但是因为 int 和 Integer 之间比较是没有意义的,所以 Java 在进行比较前会将 Integer 自动拆箱,所以最后进行的是 int 和 int 值之间的比较。由于 128 和自己相等,所以返回 true。


补充说明:


文章没有列出具体的执行环境,jdk 版本信息,因此造成不一样的结果,让大家误解了.抱歉.现在说明一下:


此文只适应于 jdk7 或以上版本,因为 jdk6 与 jdk7 的 Integer 具体实现有差别,详情可查看下源代码.

发布于: 刚刚阅读数: 3
用户头像

Steven

关注

还未添加个人签名 2023-01-09 加入

还未添加个人简介

评论

发布
暂无评论
Integer.valueOf(String) 方法之惑_Steven_InfoQ写作社区