Why do == comparisons with Integer.valueOf(String) give different results for 127 and 128?

 ie岛课 发布于 2023-02-07 10:09

I have no idea why these lines of code return different values:

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"));

The output is:

true
false
true

Why does the first one return true and the second one return false? Is there something different that I don't know between 127 and 128? (Of course I know that 127 < 128.)

Also, why does the third one return true?

I have read the answer of this question, but I still didn't get how it can return true, and why the code in second line returns false.

Makoto.. 190

There's a striking difference here.

valueOf is returning an Integer object, which may have its values cached between -128 and 127. This is why the first value returns true - it's cached - and the second value returns false - 128 isn't a cached value, so you're getting two separate Integer instances.

It is important to note that you are comparing references with Integer#valueOf, and if you are comparing a value that is larger than what the cache supports, it will not evaluate to true, even if the parsed values are equivalent (case in point: Integer.valueOf(128) == Integer.valueOf(128)). You must use equals() instead.

parseInt is returning a primitive int. This is why the third value returns true - 128 == 128 is evaluated, and is of course, true.

Now, a fair bit happens to make that third result true:

An unboxing conversion occurs with respect to the equivalence operator you're using and the datatypes you have - namely, int and Integer. You're getting an Integer from valueOf on the right hand side, of course.

After the conversion, you're comparing two primitive int values. Comparison happens just as you would expect it to with respect to primitives, so you wind up comparing 128 and 128.

啊,似乎提问者不理解Java中的基本事实:当使用"=="比较两个对象时,您正在测试它们是否是对同一对象的引用.使用"equals()"时,您正在测试它们是否具有相同的值.您不能使用"等于"来比较基元. (3认同)

@Jay不,我理解.但是最让我困惑的是为什么第一个返回true而第二个使用相同的比较方法`==`返回false.无论如何,它现在清楚了. (3认同)

@ user3152527:有一个相当大的区别 - 一个被认为是一个对象,这意味着你可以调用方法并在抽象数据结构中与它交互,比如`List`.另一个是原始的,它只是一个原始值. (2认同)


Dawood says .. 122

Integer类有一个静态缓存,存储256个特殊的Integer对象-一个用于记-128和127.这之间的每一个值,考虑这三者之间的区别.

new Integer(123);

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

Integer.parseInt("123");

int在解析之后返回原始值String.

Integer.valueOf("123");

这比其他人更复杂.它首先解析了String.然后,如果该值介于-128和127之间,则它从静态高速缓存返回相应的对象.如果该值超出此范围,则它将调用new Integer()并传入该值,以便获取新对象.

现在,考虑问题中的三个表达式.

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

返回true,因为Integer其值为127,从静态高速缓存中检索两次,并与其自身进行比较.只Integer涉及一个对象,所以返回true.

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

返回false,因为128不在静态缓存中.因此Integer,为平等的每一方创建一个新的.由于存在两个不同的Integer对象,并且==对于对象仅true在双方都是完全相同的对象时才返回,这将是false.

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

这是比较int左边的原始值128和右边的新创建的Integer对象.但是因为将a int与a 进行比较没有意义Integer,Java会Integer在进行比较之前自动取消装箱; 所以你最终比较int一个int.由于原语128等于它自己,所以返回true.

5 个回答
  • 为了补充给定的答案,还要注意以下事项:

    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

    正如用户Jay在评论中声明接受的答案时,==在对象上使用运算符时必须小心,在这里你要检查两个引用是否相同,这不是,因为它们是不同的对象,尽管它们代表了非常相同的价值.要比较对象,您应该使用该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计算)之间的整数,则返回预分配(缓存)对象.因此,当您使用127作为参数时,您将获得对同一缓存对象的两个引用并进入true引用的比较.

    2023-02-07 10:11 回答
  • 注意从这些方法返回值.该的valueOf方法返回整数实例:

    public static Integer valueOf(int i)
    

    parseInt函数方法返回整数值(原始类型):

    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")
    

    此表达式将对不同对象的引用进行比较,因为它们包含的Integer值不在<-128,127>中,因此它返回false.

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

    此表达式比较原始值(左侧)和对象(右侧)的引用,因此右侧将被解包,并且他的原始类型将与左侧进行比较,因此它返回true.

    2023-02-07 10:11 回答
  • There's a striking difference here.

    valueOf is returning an Integer object, which may have its values cached between -128 and 127. This is why the first value returns true - it's cached - and the second value returns false - 128 isn't a cached value, so you're getting two separate Integer instances.

    It is important to note that you are comparing references with Integer#valueOf, and if you are comparing a value that is larger than what the cache supports, it will not evaluate to true, even if the parsed values are equivalent (case in point: Integer.valueOf(128) == Integer.valueOf(128)). You must use equals() instead.

    parseInt is returning a primitive int. This is why the third value returns true - 128 == 128 is evaluated, and is of course, true.

    Now, a fair bit happens to make that third result true:

    An unboxing conversion occurs with respect to the equivalence operator you're using and the datatypes you have - namely, int and Integer. You're getting an Integer from valueOf on the right hand side, of course.

    After the conversion, you're comparing two primitive int values. Comparison happens just as you would expect it to with respect to primitives, so you wind up comparing 128 and 128.

    2023-02-07 10:11 回答
  • Integer objects caches between -128 and 127 of 256 Integer

    You should not compare object references with == or !=. You should use .equals(..) instead, or better - use the primitive int rather than Integer.

    parseInt: Parses the string argument as a signed decimal integer. The characters in the string must all be decimal digits, except that the first character may be an ASCII minus sign '-' ('\u002D') to indicate a negative value. The resulting integer value is returned, exactly as if the argument and the radix 10 were given as arguments to the parseInt(java.lang.String, int) method.

    valueOf Returns an Integer object holding the value extracted from the specified String when parsed with the radix given by the second argument. The first argument is interpreted as representing a signed integer in the radix specified by the second argument, exactly as if the arguments were given to the parseInt(java.lang.String, int) method. The result is an Integer object that represents the integer value specified by the string.

    equivalent to

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

    radix - the radix to be used in interpreting s

    so if you equal Integer.valueOf() for the integer inbetween

    -128 to 127 it returns true in your condition

    for lesser than -128 and greater than 127 it gives false

    2023-02-07 10:11 回答
  • Integer类有一个静态缓存,存储256个特殊的Integer对象-一个用于记-128和127.这之间的每一个值,考虑这三者之间的区别.

    new Integer(123);
    

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

    Integer.parseInt("123");
    

    int在解析之后返回原始值String.

    Integer.valueOf("123");
    

    这比其他人更复杂.它首先解析了String.然后,如果该值介于-128和127之间,则它从静态高速缓存返回相应的对象.如果该值超出此范围,则它将调用new Integer()并传入该值,以便获取新对象.

    现在,考虑问题中的三个表达式.

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

    返回true,因为Integer其值为127,从静态高速缓存中检索两次,并与其自身进行比较.只Integer涉及一个对象,所以返回true.

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

    返回false,因为128不在静态缓存中.因此Integer,为平等的每一方创建一个新的.由于存在两个不同的Integer对象,并且==对于对象仅true在双方都是完全相同的对象时才返回,这将是false.

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

    这是比较int左边的原始值128和右边的新创建的Integer对象.但是因为将a int与a 进行比较没有意义Integer,Java会Integer在进行比较之前自动取消装箱; 所以你最终比较int一个int.由于原语128等于它自己,所以返回true.

    2023-02-07 10:11 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有