【问题标题】:Strange behaviour with parameterized method on abstract class抽象类上参数化方法的奇怪行为
【发布时间】:2010-01-07 13:52:33
【问题描述】:

有人能告诉我为什么这会产生编译错误吗?我不明白为什么在第二个 for 循环中强制转换为 A 会导致 strings() 返回一般的对象列表。

import java.util.ArrayList;
import java.util.List;

public class E {

    public static void main(String[] args) {
        for (String s : new D().strings()) {
            System.out.println("s = " + s);
        }
        for (String s : ((A) new D()).strings()) {
            System.out.println("s = " + s);
        }
    }

    static class D extends A<C> {
    }

    static abstract class A<T extends B> {
        List<String> strings() {
            return new ArrayList<String>() {{
                add("Foo");
                add("Bar!");
            }};
        }
    }

    static class B {
    }

    static class C extends B {
    }
}

这是泛型的怪癖吗?

谢谢,克里斯蒂安

【问题讨论】:

    标签: java generics abstract-class parameterized


    【解决方案1】:

    行内:

        for (String s : ((A) new D()).strings()) {
    

    您正在转换为原始类型A,因此您会丢失那里的类型参数信息。在 Java 中,原始类型上的任何使用方法或字段也将导致原始类型(即使所有参数化信息都可用)——从技术上讲,原始类型或非参数化。所以A.string() 被视为原始类型List 而不是List&lt;String&gt;

    正如 JSL 在 Section 4.8 中指定的那样:

    未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.8 节、第 9.4 节)或非静态字段(第 8.3 节)的类型是擦除其在对应于 C 的泛型声明中的类型。原始类型 C 的静态成员的类型与其在对应于 C 的泛型声明中的类型相同。

    【讨论】:

    • 这真的很有趣。这就解释了为什么如果你转换为 A> 而不是 A 它可以工作。在这种情况下,您仍在使用类型化类。
    • +1 感谢您的出色回答。我删除了我自己的答案,这不如这个。
    • @Shaun,是的。在某种程度上,避免使用原始类型会惹恼你!
    • 谢谢,这就解释了。顺便说一句,它对在 1.6.0_17 上测试它的人起作用的原因是通过 msn/adium 粘贴代码时的 pebkac ... 演员被删除了,可能是因为一些格式化的事情。我的错。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 2011-03-05
    相关资源
    最近更新 更多