I want to compare to variables, both of type T extends Number
. Now I want to know which of the two variables is greater than the other or equal. Unfortunately I don't know the exact type yet, I only know that it will be a subtype of java.lang.Number
. How can I do that?
EDIT: I tried another workaround using TreeSet
s, which actually worked with natural ordering (of course it works, all subclasses of Number
implement Comparable
except for AtomicInteger and AtomicLong). Thus I'll lose duplicate values. When using List
s, Collection.sort()
will not accept my list due to bound mismatchs. Very unsatisfactory.
A working (but brittle) solution is something like this:
It's still not great, though, since it counts on
toString
returning a value parsable byBigDecimal
(which the standard JavaNumber
classes do, but which theNumber
contract doesn't demand).Edit, seven years later: As pointed out in the comments, there are (at least?) three special cases
toString
can produce that you need to take into regard:Infinity
, which is greater than everything, except itself to which it is equal-Infinity
, which is less than everything, except itself to which it is equalNaN
, which is extremely hairy/impossible to compare since all comparisons withNaN
result infalse
, including checking equality with itself.The most "generic" Java primitive number is double, so using simply
should be enough in most cases, but... there are subtle issues here when converting numbers to double. For example the following is possible with BigInteger:
results in:
Although I expect this to be very extreme case this is possible. And no - there is no generic 100% accurate way. Number interface have no method like exactValue() converting to some type able to represent number in perfect way without loosing any information.
Actually having such perfect numbers is impossible in general - for example representing number Pi is impossible using any arithmetic using finite space.
What about this one? Definitely not nice, but it deals with all necessary cases mentioned.
Let's assume that you have some method like:
If you know that there are only integers, longs and doubles can be passed as parameters then you can change method signature to:
This will work for byte, short, integer, long and double.
If you presume that BigInteger's or BigDecimal's or mix of floats and doubles can be passed then you cannot create one common method to compare all these types of parameters.
This should work for all classes that extend Number, and are Comparable to themselves.
One solution that might work for you is to work not with
T extends Number
but withT extends Number & Comparable
. This type means: "T
can only be set to types that implements both the interfaces."That allows you to write code that works with all comparable numbers. Statically typed and elegant.
This is the same solution that BennyBoy proposes, but it works with all kinds of methods, not only with comparator classes.