问题
这个问题在这里已有答案:
- 比较两个通用数字11的答案的值
有谁知道为什么java.lang.Number
没有实现Comparable
?这意味着你不能与我看来有点奇怪的分类Number
s和Collections.sort
。
发布后更新:
感谢所有有用的回复。我最终做了some more research about this topic。
java.lang.Number未实现Comparable的原因的最简单解释源于可变性问题。
对于一些评论,java.lang.Number
是抽象超类型AtomicInteger
,AtomicLong
,BigDecimal
,BigInteger
,Byte
,Double
,Float
,Integer
,Long
和Short
。在该列表中,AtomicInteger
和AtomicLong
未实现Comparable
。
四处搜寻,我发现在可变类型中实现Comparable
并不是一个好习惯,因为对象在比较期间或之后可能会发生变化,因此比较结果无用。 AtomicLong
和AtomicInteger
都是可变的。 API设计人员已经考虑到了因为它会限制未来子类型的实现,因此没有预先设定实现Comparable
。实际上,在最初实现java.lang.Number
之后很久就在Java 1.5中添加了AtomicLong
和AtomicInteger
。
除了可变性之外,这里也可能有其他考虑因素。在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做出了(合理的)决定Number
s仅为Comparable
。
#2 热门回答(41 赞)
有关答案,请参阅Java bugparadebug 4414323。你也可以从comp.lang.java.programmer找到讨论
引用Sun对2001年错误报告的回应:
所有"数字"都不具有可比性;可比较假定数字的总排序是可能的。浮点数甚至都不是这样; NaN(不是数字)既不小于,也不大于,也不等于任何浮点值,甚至本身。 {Float,Double} .compare强加一个与浮点"<"和"="运算符的排序不同的总排序。此外,如当前实现的,Number的子类仅与同一类的其他实例相当。还有其他情况,例如复数,其中不存在标准总排序,尽管可以定义一个。简而言之,Number的子类是否具有可比性应留作该子类的决定。
#3 热门回答(4 赞)
为了实现数字的可比性,你必须为每个子类对编写代码。它更容易,只是允许子类实现可比较。