为什么java.lang.Number没有实现Comparable? [重复]

问题

这个问题在这里已有答案:

  • 比较两个通用数字11的答案的值

有谁知道为什么java.lang.Number没有实现Comparable?这意味着你不能与我看来有点奇怪的分类Numbers和Collections.sort
发布后更新:
感谢所有有用的回复。我最终做了some more research about this topic

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

对于一些评论,java.lang.Number是抽象超类型AtomicInteger,AtomicLong,BigDecimal,BigInteger,Byte,Double,Float,Integer,LongShort。在该列表中,AtomicIntegerAtomicLong未实现Comparable

四处搜寻,我发现在可变类型中实现Comparable并不是一个好习惯,因为对象在比较期间或之后可能会发生变化,因此比较结果无用。 AtomicLongAtomicInteger都是可变的。 API设计人员已经考虑到了因为它会限制未来子类型的实现,因此没有预先设定实现Comparable。实际上,在最初实现java.lang.Number之后很久就在Java 1.5中添加了AtomicLongAtomicInteger

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


#1 热门回答(62 赞)

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

new Long(10).equals(new Integer(10))

永远是false,这往往会让每个人都在某个时刻绊倒。因此,你不仅不能比较任意Number,而且你甚至无法确定它们是否相等。

此外,对于真实的原始类型(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);

而你会留下一些小的差异。

所以回到制作Number``Comparable的问题。你会如何实现它?使用像doubleValue()这样的东西不可靠。记住Number个子类是:

  • 字节;
  • 短;
  • 整数;
  • 长;
  • AtomicInteger;
  • AtomicLong;
  • 漂浮;
  • 双倍;
  • BigInteger;和
  • BigDecimal。

你是否可以编写一个可靠的compareTo()方法,该方法不会转换为一系列if instanceof语句?Number实例只有六种可用的方法:

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

所以我猜Sun做出了(合理的)决定Numbers仅为Comparable


#2 热门回答(41 赞)

有关答案,请参阅Java bugparadebug 4414323。你也可以从comp.lang.java.programmer找到讨论

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

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


#3 热门回答(4 赞)

为了实现数字的可比性,你必须为每个子类对编写代码。它更容易,只是允许子类实现可比较。