通用类的父类

15
根据 泛型试用这一部分指出:
给定两个具体类型 A 和 B(例如 Number 和 Integer),无论 A 和 B 是否相关,MyClass<A> 都与 MyClass<B> 没有关系。 MyClass<A> 和 MyClass<B> 的共同父类是 Object。
然而,我们在这里被告知:
虽然 Integer 是 Number 的子类型,但 List<Integer> 不是 List<Number> 的子类型,并且实际上这两种类型没有关系。List<Number> 和 List<Integer> 的共同父类是 List<?>。
为什么第一个示例中 MyClass<A> / MyClass<B> 的父类不是 MyClass<?>?有何区别?

?的列表意味着可以是任何类型的列表。 - Amit Deshpande
好问题。期待一些很棒的答案。 - Rohit Jain
Java 中的“Object”比这更通用吗?考虑一下“Something<? extends Object>”是什么意思... - Anders R. Bystrup
1
对象是原始父类,class<?> 是通用父类。 - S.D.
3
我很惊讶到目前为止没有人提到类型擦除。如果你试图理解泛型,理解类型擦除非常重要。即使MyClass<A>MyClass<B>并不像它所述的那样相关,但在运行时,两者都变成了MyClass<Object>,因此在运行时它们是相互可转换的(这可能会导致糟糕的结果)。 - John B
@JohnB 说得好。编译器再次拯救了我们。 - S.D.
3个回答

6
我认为答案相当简单。虽然MyClass<A>MyClass<B>的正确父类确实是MyClass<?>,但教程在那里进行了小小的简化,因为通配符还没有被介绍。说出以下内容的重点:

MyClass<A>MyClass<B>的共同父类是Object

只是为了明确表示这两种类型都不是对方的父类,而与AB之间的关系无关。
这得到了您第一个引用下面的以下评论的确认:

有关如何在类型参数相关时创建两个泛型类之间的子类型关系,请参阅通配符和子类型。

以及章节通配符和子类型的介绍。
正如《泛型、继承和子类型》中所述,泛型类或接口之间并不仅仅因为它们的类型有关系就相关联。然而,您可以使用通配符来创建泛型类或接口之间的关系。

编译器是否将 MyClass<?> 视为 MyClass<Object> - wulfgarpro
@wulfgar.pro 是的。每个通用类型都会被替换为声明该类型的上限。拥有 MyClass<?> 意味着 MyClass 的声明看起来像这样:class MyClass<T>。由于 T 没有上限,因此在运行时 MyClass<?> 就是 MyClass<Object>。请参阅 http://docs.oracle.com/javase/tutorial/java/generics/genTypes.html 以获取更多信息。 - rolve
2
@wulfgar.pro 实际上,也许我误解了你的意思。 MyClass <?>擦除MyClass<Object>。但在编译时(在擦除之前),这两种类型并不完全等同。通配符实际上非常复杂,如果您有任何更多关于此的问题,您应该在SO上创建一个新的问题。但首先请检查是否有类似的问题已经被回答。 - rolve
@rolve:我认为 MyClass<?> 会被擦除为 MyClass - newacct
@newacct 是的,你说得对。我想表达的意思是:MyClass<?> 中的每个 ? 都被擦除为 Object。但是 JLS 或教程肯定有更好的表述方式。 - rolve

4

在教程的第一次引用之后,立即写道:

有关如何在类型参数相关时在两个通用类之间创建类似子类型的关系,请参阅通配符和子类型。

这是指向你的第二个引用的链接。

因此,尽管我认为它具有误导性并且措辞不太好,但我会将第一个引用解释为:

如果没有我们在以下链接中描述的通配符/子类型的能力,则MyClass和MyClass的公共父类将是Object。


不确定这是否是一个答案,但是评论无法让我放置格式。 - matt freake

1

谈论参数化类型的单一“父类”并不是真正有用的。重要的是一个东西是否是另一个东西的超类型。当然,ObjectMyClass<A>MyClass<B> 的常见超类型,MyClass<?> 也是如此。如果 A 和 B 分别是 Integer 和 Number,则 MyClass<? extends Number> 也是常见的超类型;同样适用于 MyClass<? extends Serializable>


没错,Java类型中的接口“层次结构”并不是一种树状结构。但我认为,如果我们不考虑接口,两个(参数化)类型之间会有类似于“最低公共超类型”的东西,这将成为它们的“父类”。但这个概念在实际价值上并不是很大。 - rolve

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