Is there a number “value equals”?

混江龙づ霸主 提交于 2019-12-23 10:56:58

问题


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?


回答1:


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



回答2:


This

if(100 == 100L) System.out.println("first trial happened");

you get some Binary Numeric Promotion

Otherwise, if either operand is of type long, the other is converted to long.

Therefore 100L == 100L

This

if(Integer.valueOf(100).equals(Long.valueOf(100))) {
    System.out.println("second trial was true");
} else {
    System.out.println("second trial was false");
}

"fails", because the Integer#equals() method checks if the passed object is instanceof Integer. Returns false right away if it isn't.

This

if(100d == 100l) System.out.println("third trial, fun with doubles");

Same as first, but double instead of long.

All the equals() methods of the boxed types check instanceof for their respective types, so there's no way to make them work.

You might not like the solution, but it will be something similar

if (Integer.valueOf(100).intValue() == Long.valueOf(100).longValue()) {
    System.out.println("second trial was true");
} else {
    System.out.println("second trial was false");
}



回答3:


You should use the compareTo method instead of equals when you care only about the number value.



来源:https://stackoverflow.com/questions/19410357/is-there-a-number-value-equals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!