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

发布于 2024-08-17 02:25:57 字数 805 浏览 1 评论 0原文

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

这是泛型的怪癖吗?

谢谢,克里斯蒂安

Can someone tell my why this gives a compile error? I don't see why the cast to A in the second for-loop causes strings() to return a general List of Objects.

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 {
    }
}

Is this a Generics quirk?

Thanks, Kristian

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

知你几分 2024-08-24 02:25:57

在该行中:

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

您正在转换为原始类型 A,因此您会丢失其中的类型参数信息。在 Java 中,任何使用原始类型的方法或字段也会产生原始类型(即使所有参数化信息都可用)——从技术上来说,原始类型或非参数化类型。因此,A.string() 被视为原始类型 List,而不是 List

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

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

In the line:

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

You are casting to the raw type A, so you lose the type arguments information there. In Java, any use method or field on a raw type would also result in a raw type (even if all the parameterized information is available) -- well raw type or non-parameterized technically. So A.string() is viewed as the raw type List rather than List<String>.

As the JSL specifies in Section 4.8:

The type of a constructor (§8.8), instance method (§8.8, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文