Integer.valueOf(String) 方法之惑

有个仁兄在 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而第二个判断返回了false127128有什么我不知道的区别吗?(当然除了127小于128…)
还有,为什么第三个判断返回了true
我看了另一个相关提问的回答,但是我还是不知道它们什么时候返回true还有为什么第二个判断返回false

回答#1:

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

valueOf会返回一个Integer(整型)对象,当被处理的字符串在-128127(包含边界)之间时,返回的对象是预先缓存的。这就是为什么第一行的调用会返回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");

这种情况比其他的要更复杂一些。首先进行了字符串解析,然后如果解析的值位于-128127之间,就会从静态缓存中返回对象。如果超出了这个范围,就会调用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");

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

补充说明:
文章没有列出具体的执行环境,jdk版本信息,因此造成不一样的结果,让大家误解了.抱歉.现在说明一下:
此文只适应于jdk7或以上版本,因为jdk6jdk7的Integer具体实现有差别,详情可查看下源代码.

原文链接: stackoverflow 翻译: ImportNew.com - 靳禹
译文链接: http://www.importnew.com/9162.html
[ 转载请保留原文出处、译者和译文链接。]

关于作者: 靳禹

(新浪微博:@imcom)A coder and a basketball player. Interested in programming, web security and mobile security

查看靳禹的更多文章 >>



相关文章

发表评论

Comment form

(*) 表示必填项

21 条评论

  1. 麦景行 说道:

    卧槽~ 编程时还真是要细心

    Thumb up 2 Thumb down 0

  2. Leo 说道:

    回答#2下面的第一行应该是“静态缓冲”,不是“静态穿冲”吧

    Thumb up 0 Thumb down 0

  3. notepad 说道:

    请问,我本地执行为什么返回是
    false
    false
    true

    Thumb up 0 Thumb down 0

  4. 凌迟心 说道:

    因此两个128整型对象是不用的对象….这里是不是应该是不同的对象?

    Thumb up 0 Thumb down 0

  5. xhli110 说道:

    我本地执行的也是:
    false
    false
    true
    请问下楼主的JDK版本号是多少?我的version : 1.6.0_10-rc2
    QQ:757590384

    Thumb up 0 Thumb down 1

  6. maosi 说道:

    1、大小写问题“你实际进行比较的是integer.valueOf返回的对象引用”
    2、Integer a = 1;实际上也是调用的是Integer.valueOf(1);

    Thumb up 1 Thumb down 0

  7. 李晖 说道:

    楼主是土鳖
    public static Integer valueOf(String s) throws NumberFormatException
    {
    return new Integer(parseInt(s, 10));
    }
    这个是 类型为string的方法 一看显然应该是false的。

    Thumb up 1 Thumb down 5

  8. lm 说道:

    试了下,
    Integer.valueOf(127) == Integer.valueOf(127) 返回的是true
    但是
    Integer.valueOf(“127″) == Integer.valueOf(“127″)返回的是false
    缓存的情况貌似只适用于int值的情况,对于string,都是要利用parseInt解析的,所以即使是 -128 <= i <= 127仍然是2个对象

    Thumb up 2 Thumb down 0

  9. 黄锐东 说道:

    搞了两年java了 ,还不真知道int类型的值有静态缓存这么一说 ,长知识了~~

    Thumb up 1 Thumb down 0

  10. binwayne 说道:

    JDK6 和JDK7 在valueOf(String s)上并无差异

    Thumb up 2 Thumb down 0

  11. window 说道:

    这样子说,parseInt的效率比高吗?

    Thumb up 1 Thumb down 0

  12. chenssy 说道:

    还真没有注意到这些细节

    Thumb up 1 Thumb down 0

  13. wanghaoinfo 说道:

    学习了。真心不错

    Thumb up 1 Thumb down 0

  14. blackwiz 说道:

    感觉会有这种和直觉上违背的问题的主要原因是java不能进行运算符重载…

    Thumb up 0 Thumb down 0

  15. 小葫芦丶 说道:

    本身对象比较用 == 合适吗?

    Thumb up 0 Thumb down 0

  16. 康寿伟 说道:

    常量池技术。

    Thumb up 0 Thumb down 0

  17. itbokeyun 说道:

    很讨厌这样的问题作为面试题

    Thumb up 0 Thumb down 0

跳到底部
返回顶部