抽象类的参数化方法的奇怪行为

Kri*_*ian 5 java generics abstract-class parameterized

有人能告诉我为什么会出现编译错误吗?我不明白为什么在第二个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 {
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个泛型怪癖吗?

谢谢,克里斯蒂安

not*_*oop 7

在线:

    for (String s : ((A) new D()).strings()) {
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 这真的很有趣.这就解释了为什么如果你转向A <?>而不仅仅是A它有效.在这种情况下,您仍在使用类型化的类. (3认同)