Does anyone know why java.lang.Number
does not implement Comparable
? This means that you cannot sort Number
s with Collections.sort
which seems to me a little strange.
Post discussion update:
Thanks for all the helpful responses. I ended up doing some more research about this topic.
The simplest explanation for why java.lang.Number does not implement Comparable is rooted in mutability concerns.
For a bit of review, java.lang.Number
is the abstract super-type of AtomicInteger
, AtomicLong
, BigDecimal
, BigInteger
, Byte
, Double
, Float
, Integer
, Long
and Short
. On that list, AtomicInteger
and AtomicLong
to do not implement Comparable
.
Digging around, I discovered that it is not a good practice to implement Comparable
on mutable types because the objects can change during or after comparison rendering the result of the comparison useless. Both AtomicLong
and AtomicInteger
are mutable. The API designers had the forethought to not have Number
implement Comparable
because it would have constrained implementation of future subtypes. Indeed, AtomicLong
and AtomicInteger
were added in Java 1.5 long after java.lang.Number
was initially implemented.
Apart from mutability, there are probably other considerations here too. A compareTo
implementation in Number
would have to promote all numeric values to BigDecimal
because it is capable of accommodating all the Number
sub-types. The implication of that promotion in terms of mathematics and performance is a bit unclear to me, but my intuition finds that solution kludgy.
It's worth mentioning that the following expression:
new Long(10).equals(new Integer(10))
is always false
, which tends to trip everyone up at some point or another. So not only can you not compare arbitrary Number
s but you can't even determine if they're equal or not.
Also, with the real primitive types (float
, double
), determining if two values are equal is tricky and has to be done within an acceptable margin of error. Try code like:
double d1 = 1.0d;
double d2 = 0.0d;
for (int i=0; i<10; i++) {
d2 += 0.1d;
}
System.out.println(d2 - d1);
and you'll be left with some small difference.
So back to the issue of making Number
Comparable
. How would you implement it? Using something like doubleValue()
wouldn't do it reliably. Remember the Number
subtypes are:
Byte
;Short
;Integer
;Long
;AtomicInteger
;AtomicLong
;Float
;Double
;BigInteger
; andBigDecimal
.Could you code a reliable compareTo()
method that doesn't devolve into a series of if instanceof statements? Number
instances only have six methods available to them:
byteValue()
;shortValue()
;intValue()
;longValue()
;floatValue()
; anddoubleValue()
.So I guess Sun made the (reasonable) decision that Number
s were only Comparable
to instances of themselves.