为什么java.lang.Integer没有继承java.lang.Long?

3

可以将整数值分配到长变量中。 可以自动装箱整数值为Long引用变量。 但是将Integer对象分配给Long引用变量不可能。

我的观点是Integer / integer是Long / long支持的特定值范围。

因此,层次结构应为Integer扩展Long和Long扩展数字。

欢迎评论。


4
如果有什么不合理的话,反过来问可能更有意义,但无论哪种情况下的答案都是“因为它们就是这样设计的”。 - user207421
2
@EJP 不完全如此:如果我们仅考虑数字范围,则每个整数也是长整型,但反过来不成立。 - Henry
有趣的问题。但是除了Eran提出的存储问题之外,我猜想由于Java语言特别处理装箱类,将它们作为子类可能会导致其他一些问题,例如使当前不含歧义的某些表达式变得模棱两可。我不能确定这是否属实,但是语言设计者必须尝试考虑边角情况,并设法预见每种语言元素的组合方式,以确保没有问题。 - ajb
@Henry 这正是为什么反过来也至少同样有意义的原因。长整型的范围超出了整型的范围。 - user207421
1
@EJP 不可以,你可以像将子类的对象分配给超类变量一样将整数分配给长整型变量,但不能将长整型分配给整数。在面向对象的意义上,“extends”确实限制了允许的值集合。例如,可能存在比字符串更多的可能对象。 - Henry
显示剩余2条评论
2个回答

8
一个 Long 包含一个成员变量 (value),它保存着这个 Long 的值。
如果 IntegerLong 的子类,那么 Integer 要么使用基类的那个 long 成员变量,这样会浪费空间(因为 long 占用的字节数是 int 的两倍),要么忽略它并使用自己的 int 成员变量,这样更加浪费空间(因为在这种情况下,Integer 类将包含自己的 int 成员变量和基类的 long 成员变量)。
原始类型的包装器应该尽可能地高效(因为在某些情况下你必须使用它们,例如不能直接持有原始类型的 Collection)。因此,任何会增加 Integer 存储空间的类层次结构都不是一个好主意。

4
原因很简单: 如果整数扩展为长整型,那么整数的实例也将成为长整型的实例:
Integer i = 0;
if (i instanceof Long) 
    // yes! oops... Integer would be a Long

显然,在数学上这不是事实,也不应该是。

不要将共享值范围的类型与需要类型共享类层次结构的情况混淆。


关于存储等问题的讨论是实现细节,与本问题所涉及的语言设计考虑无关。


虽然我倾向于同意 Integer 不应该扩展 Long,但我不确定为什么这在数学上 "显然不是这种情况",因为作为一个 Integer 的每个数字都属于 Long 所涵盖的数字子集。你能详细说明一下你对这个声明的理解吗? - ajb
1
@ajb 好的 - 情感化语言已经删除,但是 1)如果说 Long 可以被认为是 Integer 的扩展,而不是反过来,2)一个 Integer 不是 Long。Double 可以准确地表示每个 Integer 值 - 这是否意味着 Double 是 Integer 或者反之亦然?不是的。它们是共享一些值范围的类,它们是数字,但仅此而已。数学行为是不同的:Integer 溢出而 Long 不会。此外,从 Java 语言规范的角度来看,它们是原始类型的包装类,并且自动装箱到特定类是 JLS 的一部分。 - Bohemian
啊,我错过了运算符由于包装而返回不同数学结果的情况——这似乎是最清晰的“数学”理由。是的,仅凭这一点就足以成为不使用子类的好理由。我认为这样做会违反LSP原则。 - ajb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接