0

If this is a duplicate I'll happily delete it, but I am unable to find it.

Why does does the 2nd comparison return false? Thanks.

$ cat test.java 

class test {
public static void main(String[] args) {
        Integer num1 = new Integer(0);
        Integer num2 = new Integer(0);
        num1 = 1;
        num2 = 1;

        if (num1 == num2) {
            System.out.println("Numbers are equal");
        }
        num1 = 128;
        num2 = 128;
        if (num1 == num2) {
            System.out.println("Numbers are equal using == ");
                }
        if (num1.equals(num2)) {
            System.out.println("Numbers are equal using .equals");
        }
    }
}
$ javac test.java 
$ java test
Numbers are equal
Numbers are equal using .equals
Mike Makuch
  • 1,788
  • 12
  • 15
  • 3
    Integers -128 through 127 are cached internally to use the same `Integer` instance. All other values, however, create a new `Integer` upon each declaration, so `num1` and `num2` are two different `Integer` objects. This question has been asked before, but I don't have a link to such a duplicate. – FThompson Nov 26 '13 at 00:46
  • @Vulcan you were the 1st to answer the question. Submit it as an answer and I'll mark it as answered. Thanks. – Mike Makuch Nov 26 '13 at 00:49
  • 2
    @koodawg Thanks, but I try to avoid answering duplicate questions if I know that they've been answered before, because often in cases like this, my knowledge stems from having seen the answers to the similar question(s). It'd feel unfair to receive reputation in re-posting a reworded version of what someone else has written in an answer. – FThompson Nov 26 '13 at 00:56

2 Answers2

4

In Java, Integers should be compared using equals(), because they're object types, not primitives. The first example works because Java creates a pool of Integers between -128 and 127 (although this range can be configured), and all identity comparisons between them (using ==) will work, because the numbers are retrieved from the pool. Larger numbers are created new each time, and the identity comparison won't work for them - that's why, to play it safe, all equality comparisons between objects must be made using equals(), which will always work. As you just witnessed, using == will work sometimes, but not always.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • Re "Integers should be compared using equals" - yes, I know that. That was not my question. Thanks. – Mike Makuch Nov 26 '13 at 00:50
  • 2
    This answers your question entirely, no need to put on an attitude. – Jeroen Vannevel Nov 26 '13 at 00:51
  • @koodawg, the answer lies in the sentence immediately after that. – SimonT Nov 26 '13 at 00:51
  • 1
    *Now* it answers my question, after the verbiage about the cache between -128 and 127 was added. No attitude. Thank you. – Mike Makuch Nov 26 '13 at 00:53
  • I don't see any edit history on the answer. Were you watching the answer being typed out or loaded one sentence at a time? Or just not being a good community member? – SimonT Nov 26 '13 at 00:56
  • 1
    @SimonT Any edits within the first 5 minutes don't show up in the edit history, so it's *possible* that the answer was edited after the comment. – Dennis Meng Nov 26 '13 at 01:09
1

Because num1 and num2 are declared as Integer types, rather than primitive int types, the assignments use autoboxing. The de-sugaring process uses the Integer.valueOf(int) method to make the conversion from int to Integer. This method is not required to cache Integer objects for values of 128 or more, and so a new instance is created each time the value 128 is auto-boxed.

When these two distinct objects are tested for reference equality, the result is false. For values from -128 to 127, the result will be true, because the cache used by the valueOf() method consistently returns the same instance.

erickson
  • 265,237
  • 58
  • 395
  • 493