Why are these == but not `equals()`?

后端 未结 8 1644
灰色年华
灰色年华 2020-12-01 07:58

I\'m a bit confused about the way Java treats == and equals() when it comes to int, Integer and other types of numbers.

相关标签:
8条回答
  • 2020-12-01 08:28

    The reason for

    X == y
    

    being true has to do with binary numeric promotion. When at least one operand to the equality operator is convertible to a numeric type, the numeric equality operator is used. First, the first operand is unboxed. Then, both operands are converted to int.

    While

    X.equals(y)
    

    is a normal function call. As has been mentioned, y will be autoboxed to a Short object. Integer.equals always returns false if the argument is not an Integer instance. This can be easily seen by inspecting the implementation.

    One could argue that this is a design flaw.

    0 讨论(0)
  • 2020-12-01 08:28

    I remember a good practice for overriding "equal(object obj)" is of first checking the type of the parameter passed in. So perhap this causes X.equals(Y) to be false. You might check the souce code to dig out the truth :)

    0 讨论(0)
  • 2020-12-01 08:28

    Java will convert an Integer into an int automatically, if needed. Same applies to Short. This feature is called autoboxing and autounboxing. You can read about it here.

    It means that when you run the code:

    int a = 5;
    Integer b = a;
    System.out.println(a == b);
    

    Java converts it into:

    int a = 5;
    Integer b = new Integer(a);
    System.out.println(a == b.valueOf());
    
    0 讨论(0)
  • 2020-12-01 08:40

    Your problem here is not only how it treats == but autoboxing... When you compare Y and 9 you are comparing two primitives that are equal, in the last two cases you get false simply because that's how equals work. Two objects are equal only if they are of the same kind and have the same value. When you say in "X.equals(y)" you are telling it to do Integer.equals(Short) and looking at the implementation of Integer.equals() it will fail:

       public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
        }
    

    Because of autoboxing the last two will result in the same failure as they will both be passed in as Shorts.

    Edit: Forgot one thing... In the case of results.add(X == y); it will unbox X and do (X.intValue() == y) which happens to be true as well as 9 == 9

    0 讨论(0)
  • 2020-12-01 08:44

    (small) Integer instances are cached, so the invariant x == y is holded for small instances (actually -127 +128, depends on JVM):

    Integer a = 10;
    Integer b = 10;
    
    assert(a == b); // ok, same instance reused
    
    a = 1024;
    b = 1024;
    
    assert(a == b); // fail, not the same instance....
    assert(a.equals(b)); // but same _value_
    

    EDIT

    4) and 5) yield false because equals check types: X is an Integer whereas Y is a Short. This is the java.lang.Integer#equals method:

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
    
        return false;
    }
    
    0 讨论(0)
  • 2020-12-01 08:47

    This automatic conversion is called autoboxing.

    0 讨论(0)
提交回复
热议问题