当前位置: 首页 > 面试题库 >

为什么java.lang.Number不实现Comparable?

凌联
2023-03-14
问题内容

有谁知道为什么
java.lang.Number不执行Comparable?这意味着您无法对排序NumberCollections.sort这在我看来有点奇怪。

讨论后更新:

感谢所有有用的回复。最后,我对该主题进行了更多研究。

为什么java.lang.Number不实现Comparable的最简单解释源于可变性问题。

对于位的检讨,java.lang.Number是抽象的超类型的AtomicIntegerAtomicLongBigDecimalBigIntegerByteDoubleFloatIntegerLongShort。在该列表中,AtomicIntegerAtomicLong以没有实现Comparable

深入研究,我发现Comparable在可变类型上实现不是一种好习惯,因为在比较期间或之后对象可能会更改,从而使比较结果无效。这两个AtomicLongAtomicInteger是可变的。API设计人员事先就没有Number实现,Comparable因为这样会限制将来子类型的实现。确实,AtomicLong并且AtomicIntegerjava.lang.Number最初实现之后很久就在Java
1.5中添加了它们。

除了可变性之外,这里可能还需要考虑其他因素。中的compareTo实现Number必须将所有数值都提升为,BigDecimal因为它能够容纳所有Number子类型。对于我来说,这种提升对数学和性能的影响还不清楚,但是我的直觉发现这种解决方法很混乱。


问题答案:

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

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

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

另外,在实原语类型(floatdouble),确定是否两个值相等是棘手的,并且必须在可接受的误差容限内完成。尝试如下代码:

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子类型为:

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

您能否编写一个compareTo()不会分解为一系列if instanceof语句的可靠方法? Number实例只有六个可用方法:

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

因此,我想Sun做出了(合理的)决定,即Numbers仅Comparable针对自己的实例。



 类似资料:
  • 问题内容: 你知道吗 : 将输出: 这是由于(继承自)未覆盖的事实引起的。 您知道为什么会这样吗? 问题答案: 根据的合同,没有针对s 的通用equals()方法,因此无法提供一个。 请注意,它既不是Set也不是List,因此既不是数量也不是它不支持的原因。

  • 我现在想要一个数据结构,就像一个有索引的Deque。因此,它应该有O(1)在前面和后面添加和删除元素,以及O(1)基于索引访问元素。这并不难想象一个适合这种情况的设置。 ArrayDeque似乎是一个自然的选择。但是,ArrayDeque不实现List。由于底层数据结构是一个数组,是否有充分的理由不允许索引? 还有,更实用的是,有人知道有哪个图书馆在做我想做的事情吗。据我所知,Apache Com

  • 问题内容: 我正在将某些东西从Java移植到C#。在Java中,a 取决于其中的项目。在C#中,我总是从… 获取相同的哈希码。 为什么是这样? 对于我的某些对象,哈希码必须有所不同,因为其list属性中的对象使对象不相等。我希望哈希码对于对象的状态始终是唯一的,并且仅在对象相等时才等于另一个哈希码。我错了吗? 问题答案: 为了正常工作,散列码必须是不可变-一个对象的散列码必须 永远不会 改变。 如

  • 问题内容: 在我对Servlet的理解中,该Servlet将由Container实例化,其方法将被调用一次,并且Servlet将像单例一样存活,直到JVM关闭。 我不希望我的servlet被序列化,因为当应用服务器恢复或正常启动时,它将被重新构造。Servlet不应该包含特定于会话的成员,因此将其写入磁盘并重新实例化是没有意义的。有实际用途吗? 我担心的是,我在其中放置了一些不可序列化的字段,然后

  • 我没有受过CS方面的教育,但我已经专业地用Java编程近十年了,我从未见过任何人在生产系统中实现。这并不意味着它没有它的用途,或者和我一起工作的人一直在做正确的事情。 所以我的问题是,有哪些实现的用例不能通过语言中的另一个进程或语法更可靠地处理? 请提供具体的场景或您的经验,简单地重复一本Java教科书,或者Finalize的预期用途是不够的,因为这不是本问题的意图。

  • 也许我没有看到什么或者我忘记了在计算运行时考虑的事情,所以请告诉我。