为什么java.lang.Number没有实现Comparable?

Jul*_*ang 132 java sorting comparable

有谁知道为什么 java.lang.Number不实施Comparable?这意味着你无法排序Numbers的Collections.sort这对我来说有点陌生.

发布讨论更新:

感谢所有有用的回复.我最后对这个话题进行了更多的研究.

java.lang.Number未实现Comparable的原因的最简单解释源于可变性问题.

对于位的检讨,java.lang.Number是抽象的超类型的AtomicInteger,AtomicLong,BigDecimal,BigInteger,Byte,Double,Float,Integer,LongShort.在那个列表上,AtomicIntegerAtomicLong没有实现Comparable.

四处搜索,我发现Comparable在可变类型上实现这不是一个好习惯,因为对象在比较期间或之后可能会发生变化,因此比较结果无用.这两个AtomicLongAtomicInteger是可变的.API设计者已经预见到没有Number实现,Comparable因为它会限制未来子类型的实现.确实,AtomicLong并且AtomicIntegerjava.lang.Number最初实现之后很久就被添加到Java 1.5中.

除了可变性之外,这里也可能有其他考虑因素.一compareTo实施Number就必须促进所有的数字值BigDecimal,因为它是能够容纳所有的Number子类型.这种促销在数学和表现方面的含义对我来说有点不清楚,但我的直觉发现了解决方案.

cle*_*tus 63

值得一提的是以下表达式:

new Long(10).equals(new Integer(10))
Run Code Online (Sandbox Code Playgroud)

永远是false,这往往会使每个人在某个时刻绊倒.因此,您不仅无法比较任意Numbers,而且甚至无法确定它们是否相等.

此外,对于真实的原始类型(float,double),确定两个值是否相等是棘手的,并且必须在可接受的误差范围内完成.尝试以下代码:

double d1 = 1.0d;
double d2 = 0.0d;
for (int i=0; i<10; i++) {
  d2 += 0.1d;
}
System.out.println(d2 - d1);
Run Code Online (Sandbox Code Playgroud)

你会留下一些小小的差异.

所以回到制作的问题Number Comparable.你会如何实现它?使用类似的东西是doubleValue()不可靠的.记住Number子类型是:

  • Byte;
  • Short;
  • Integer;
  • Long;
  • AtomicInteger;
  • AtomicLong;
  • Float;
  • Double;
  • BigInteger; 和
  • BigDecimal.

你能编写一个compareTo()不会转换成一系列if instanceof语句的可靠方法吗? Number实例只有六种可用的方法:

  • byteValue();
  • shortValue();
  • intValue();
  • longValue();
  • floatValue(); 和
  • doubleValue().

所以我猜Sun做出的(合理的)决定Number只是Comparable针对自己的例子.

  • Thxs Cletus.恕我直言应该有一个中间数字类型,如RealNumber(见上文)封装Float,Double,Long,Integer,Short).否则,您缺少多态性,最终导致这些类型的代码重复以及相应的未装箱原始类型. (11认同)
  • 对于理解系统的专家用户来说,这可能会更令人困惑……或者可能不会。对于专家用户来说,它也会更简单。Collections API 中也进行了同样的权衡。存在许多对某些底层实现没有意义的抽象方法。Sun 没有从 API 中排除方法并要求程序员检查实现的类型,而是选择使用方法的抽象版本,并建议在实现不支持该方法时抛出异常。请参阅“List.set”、“Map.put”、“Set.remove”等等。 (2认同)

Edd*_*die 42

有关答案,请参阅Java bugparade bug 4414323.您还可以从comp.lang.java.programmer中找到讨论

引用Sun对2001年错误报告的回应:

所有"数字"都不具有可比性; 可比较假定数字的总排序是可能的.浮点数甚至都不是这样; NaN(不是数字)既不小于,也不大于,也不等于任何浮点值,甚至本身.{Float,Double} .compare强加一个不同于浮点"<"和"="运算符排序的总排序.此外,如当前实现的那样,Number的子类仅与同一类的其他实例相当.还有其他情况,例如复数,其中不存在标准总排序,尽管可以定义一个.简而言之,Number的子类是否具有可比性应留作该子类的决定.

  • 艾迪:谢谢你的链接.我同意错误报告,该报告说Java需要一个RealNumber类型,它将是所有数字类型的超类,并具有相应的原始数字类型(例如Float等).如果没有Java,使用Java中的数字仍然很困难. (2认同)
  • Sun本可以选择一个程序员可以覆盖的合理默认值.这不是借口.对于空字符串或空引用,字符串存在同样的问题.null引用是否大于或小于字符串"foo"?Sun选择了有意义的订购. (2认同)

z *_* - 5

为了实现数量上的可比性,您必须为每个子类对编写代码。相反,只允许子类实现可比较更容易。


Jai*_*aiz 5

为了尝试解决原始问题(对数字列表进行排序),一种选择是声明扩展 Number 并实现 Comparable 的泛型类型的列表。

就像是:

<N extends Number & Comparable<N>> void processNumbers(List<N> numbers) {
    System.out.println("Unsorted: " + numbers);
    Collections.sort(numbers);
    System.out.println("  Sorted: " + numbers);
    // ...
}

void processIntegers() {
    processNumbers(Arrays.asList(7, 2, 5));
}

void processDoubles() {
    processNumbers(Arrays.asList(7.1, 2.4, 5.2));
}
Run Code Online (Sandbox Code Playgroud)