4

When executing the following code snippet it behaves differently for Double.

Long v1 = 1L;
Long v2 = 1L;
Double d1 = 1.0;
Double d2 = 1.0;

System.out.println(v1 == v2); // Prints true
System.out.println(d1 == d2); // Prints false

System.out.println(v1.equals(v2)); // Prints true
System.out.println(d1.equals(d2)); // Prints true

Why Double == behaves differently from Long?

João Pedro Schmitt
  • 1,046
  • 1
  • 11
  • 25
  • @Tschallacka I doubt it does. – Thomas Jan 30 '20 at 14:02
  • 1
    https://stackoverflow.com/questions/13098143/why-does-the-behavior-of-the-integer-constant-pool-change-at-127 Probably something similar going on for Longs. That is, for small values there's a pool of existing `Long` instances that will be used instead of creating new instances all the time. – Michael Jan 30 '20 at 14:03
  • 4
    because `==` checks for object identity, not equality –  Jan 30 '20 at 14:03
  • @a_horse_with_no_name heh, didn't notice he invoked Objects. Yea, that'd do it. – Tschallacka Jan 30 '20 at 14:04
  • 2
    Unrelated to this problem, but comparing floating point values in general is not as easy as one might expect. See e.g. [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). – Some programmer dude Jan 30 '20 at 14:04

1 Answers1

4
Long v1 = 1L;
Long v2 = 1L;
Double d1 = 1.0;
Double d2 = 1.0;

You are creating two references to objects here, and instantiating two objects with autoboxing behaviour of Java.

Java re-uses the same Long object instance from a pool for v1 and v2, The Doubles do not use a pool for remembering values, as can be read in this informative blog entry https://gerardnico.com/code/type/autoboxing

Here are some rules as with Java 5 :

autoboxing to Boolean and Byte always returns an object from the pool
autoboxing to Char, Short, Integer and Long returns an object from the pool when the autoboxed value is between -128 and 127 (inclusive)
autoboxing of Float and Double does not use the pool and always returns a new object

Your code becomes then with autoboxing(some pool is a visualisation of the pool java uses to cache certain values):

class SomePoolJavaUses {
   static Long _l1 = new Long(1L);
   static Long _l2 = new Long(2L);
   static Long _l3 = new Long(3L);
   ...
}

Long v1 = SomePoolJavaUses._l1;
Long v2 = SomePoolJavaUses._l1;
Double d1 = new Double(1.0);
Double d2 = new Double(1.0);

This means that d1 and d2 are not equal instances, so they are not equal in ==
This means that v1 and v2 are equal instance, so they are equal in ==

the v1.equals returns true, because there is being looked at the actual value there instead of a quick check if the memory addresses are the same.

Tschallacka
  • 27,901
  • 14
  • 88
  • 133