Why doesn't java.lang.Number implement Compara

2019-01-04 19:22发布

This question already has an answer here:

Does anyone know why java.lang.Number does not implement Comparable? This means that you cannot sort Numbers 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.

12条回答
老娘就宠你
2楼-- · 2019-01-04 19:42

in order to implement comparable on number, you would have to write code for every subclass pair. Its easier instead to just allow subclasses to implement comparable.

查看更多
你好瞎i
3楼-- · 2019-01-04 19:42

Looking at the class hierarchy. Wrapper classes like Long, Integer, etc, implement Comparable, i.e. an Integer is comparable to an integer, and a long is comparable to a long, but you can't mix them. At least with this generics paradigm. Which I guess answers your question 'why'.

查看更多
SAY GOODBYE
4楼-- · 2019-01-04 19:44

Very probably because it would be rather inefficient to compare numbers - the only representation into which every Number can fit to allow such comparison would be BigDecimal.

Instead, non-atomic subclasses of Number implements Comparable itself.

Atomic ones are mutable, so can't implement an atomic comparison.

查看更多
爷、活的狠高调
5楼-- · 2019-01-04 19:47

For the answer, see Java bugparade bug 4414323. You can also find a discussion from comp.lang.java.programmer

To quote from the Sun response to the bug report from 2001:

All "numbers" are not comparable; comparable assumes a total ordering of numbers is possible. This is not even true of floating-point numbers; NaN (not a number) is neither less than, greater than, nor equal to any floating-point value, even itself. {Float, Double}.compare impose a total ordering different from the ordering of the floating-point "<" and "=" operators. Additionally, as currently implemented, the subclasses of Number are only comparable to other instances of the same class. There are other cases, like complex numbers, where no standard total ordering exists, although one could be defined. In short, whether or not a subclass of Number is comparable should be left as a decision for that subclass.

查看更多
Explosion°爆炸
6楼-- · 2019-01-04 19:51

You can use Transmorph to compare numbers using its NumberComparator class.

NumberComparator numberComparator = new NumberComparator();
assertTrue(numberComparator.compare(12, 24) < 0);
assertTrue(numberComparator.compare((byte) 12, (long) 24) < 0);
assertTrue(numberComparator.compare((byte) 12, 24.0) < 0);
assertTrue(numberComparator.compare(25.0, 24.0) > 0);
assertTrue(numberComparator.compare((double) 25.0, (float) 24.0) > 0);
assertTrue(numberComparator.compare(new BigDecimal(25.0), (float) 24.0) > 0);
查看更多
放我归山
7楼-- · 2019-01-04 19:51

My guess is that by not implementing Comparable, it give more flexibility to implementing classes to implement it or not. All the common numbers (Integer, Long, Double, etc) do implement Comparable. You can still call Collections.sort as long as the elements themselves implement Comparable.

查看更多
登录 后发表回答