Search code examples
javanumbersequalsprimitive

Is there a number "value equals"?


By default, Java does Binary Numeric Promotion for primitives, but does not do the same thing for objects. Here's a quick test to demonstrate:

public static void main(String... args) {
  if(100 == 100L) System.out.println("first trial happened");
  if(Integer.valueOf(100).equals(Long.valueOf(100))) {
    System.out.println("second trial was true");
  } else {
    System.out.println("second trial was false");
  }
  if(100D == 100L) System.out.println("third trial, fun with doubles");
}

Output:

first trial happened
second trial was false
third trial, fun with doubles

This is obviously correct behavior - an Integer is not a Long. However, does there exist a "value equals" for Number subclasses that would return true the same way that 100 == 100L returns true? Or 100d == 100L? In other words, is there a method (that is not Object.equals) that will do the equivalent of the Binary Numeric Promotion behavior for objects?


Solution

  • Guava provides several nice utilities for working with primitives, including a compare() method for each type:

    int compare(prim a, prim b)
    

    And in fact, this same functionality has been added to the JDK as of Java 7. These methods don't provide arbitrary Number comparisons, however they give you the granularity to define any type-safe comparison you'd like, by choosing which class (Longs, Doubles, etc.) to use.

    @Test
    public void valueEquals() {
      // Your examples:
      assertTrue(100 == 100l);
      assertTrue(100d == 100l);
      assertNotEquals(100, 100l); // assertEquals autoboxes primitives
      assertNotEquals(new Integer(100), new Long(100));
    
      // Guava
      assertTrue(Longs.compare(100, 100l) == 0);
      assertTrue(Longs.compare(new Integer(100), new Long(100)) == 0);
      assertTrue(Doubles.compare(100d, 100l) == 0);
      // Illegal, expected compare(int, int)
      //Ints.compare(10, 10l);
    
      // JDK
      assertTrue(Long.compare(100, 100l) == 0);
      assertTrue(Long.compare(new Integer(100), new Long(100)) == 0);
      assertTrue(Double.compare(100d, 100l) == 0);
      // Illegal, expected compare(int, int)
      //Integer.compare(10, 10l);
      // Illegal, expected compareTo(Long) which cannot be autoboxed from int
      //new Long(100).compareTo(100);
    }