【问题标题】:Do List<List<T>> and List<T> have the same raw-type?List<List<T>> 和 List<T> 是否具有相同的原始类型?
【发布时间】:2019-09-15 22:59:11
【问题描述】:

我有一个类X,它有以下方法:

public <T> List<T> g(List<T> l) {…}

我还有一个类 Y 扩展类 X 并具有以下方法:

public <T> List<T> g(List<List<T>> l) {…}

据我了解,在类型擦除过程之后,它们都具有相同的原始类型。为什么 Java 不将 Y::g 视为 X::g 的覆盖方法并且无法编译代码?如果在g 中我们有ArrayList 而不是List

【问题讨论】:

  • IIRC 确实具有相同的原始类型,但类型擦除更多的是运行时的事情,而不是编译时的事情。如果明天没有答案,我会写一个正确的答案。
  • 当你不覆盖它们时,为什么要把这两种方法都视为被覆盖?仅仅因为类型将在编译期间被删除并不意味着它们永远不会被考虑。
  • 你能提供你的完整代码吗?这不适合我。 ideone.com/bfsDKD
  • @k5_ 就像 OP 说的那样。
  • 当我尝试按照您所说的操作时,我得到了您所期望的确切错误(它们具有相同的擦除,但不会相互覆盖)。请出示您的完整代码。 (假设你问为什么你没有得到这个编译错误 - 我看到你可以用两种相反的方式阅读你的问题 - 请澄清)

标签: java type-erasure raw-types


【解决方案1】:

根据JLSY.g 会覆盖X.g,特别是如果Y.gX.g 的子签名。

Y.gsubsignatureX.g 仅当:

  • Y.gX.g 具有相同的签名,即:public &lt;T&gt; List&lt;T&gt; g(List&lt;T&gt; l);

  • 或者Y.g的签名和X.g的签名擦除一样:

    因此,在这种情况下,Y.g 可能是 public List g(List l)

根据您的描述,这些条件都不成立,因此出现错误。

【讨论】:

    【解决方案2】:

    我相信你误解了类型擦除。 Java 中泛型的要点是在编译期间允许更严格的类型检查,这仍然允许在运行时共享代码。为此,编译器会在编译期间“擦除”该类型。当您在运行时使用反射检查类型时,这一点很重要。

    因此,在您的情况下,编译器正确区分了两种不同的类型。这些在运行时被区别对待的事实对它们的签名没有影响。

    有关该主题的介绍,请参阅https://docs.oracle.com/javase/tutorial/java/generics/erasure.html 或有关正式规范的https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.6

    【讨论】:

    • 那么你认为他在编译时会出错还是不会出错?听起来您认为他没有收到错误,而实际上他确实收到了,因为这两种方法在类型擦除后具有相同的签名。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多