无法对通用子类进行静态引用 (Java)

发布于 2024-07-15 20:21:18 字数 778 浏览 6 评论 0 原文

我有以下代码:

class SuperClass {
    public static String getName() { return "super"; }
}

class SubClass extends SuperClass {
    public static String getName() { return "sub"; }
}

public class Dummy<T extends SuperClass> {
    public void print() {
        System.out.println("SuperClass: " + SuperClass.getName());
        System.out.println("SubClass: " + SubClass.getName());
        System.out.println("T: " + T.getName());
    }
    public static void main(String[] args) {
        new Dummy<SubClass>().print();
    }
}

该代码输出以下内容:

SuperClass: super
SubClass: sub
T: super

我的问题是: 为什么 T.getName() 不返回 SubClass.getName() 的值? 毕竟,我指定了 T == SubClass。 或者静态函数调用对于泛型引用无效吗?

预先非常感谢!

I have the following code:

class SuperClass {
    public static String getName() { return "super"; }
}

class SubClass extends SuperClass {
    public static String getName() { return "sub"; }
}

public class Dummy<T extends SuperClass> {
    public void print() {
        System.out.println("SuperClass: " + SuperClass.getName());
        System.out.println("SubClass: " + SubClass.getName());
        System.out.println("T: " + T.getName());
    }
    public static void main(String[] args) {
        new Dummy<SubClass>().print();
    }
}

This code outputs the following:

SuperClass: super
SubClass: sub
T: super

My question is:
Why doesn't T.getName() return the value of SubClass.getName()? After all, I specified that T == SubClass. Or are static function calls invalid for generic references?

Thanks a lot in advance!

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

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

发布评论

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

评论(3

掐死时间 2024-07-22 20:21:18

这不仅仅是一个关于泛型的问题。

如果你说:

SuperClass obj = new SubClass();
System.out.println(obj.getName());

你也会得到“超级”。 不存在“多态”静态方法。

在您的情况下,编译器对 T 的了解就是它扩展了 SuperClass,因此它将调用 SuperClass.getName()

This isn't just an issue about generics.

If you say:

SuperClass obj = new SubClass();
System.out.println(obj.getName());

you will also get "super". There are no "polymorphic" static methods.

In your case, all the compiler knows about T is that it extends SuperClass, so it will call SuperClass.getName().

清风夜微凉 2024-07-22 20:21:18

与 C++ 模板不同,Java 泛型通过类型擦除来工作,因此它只为 T 的所有值生成一个类,并将该类中对类型 T 的所有引用转换为超类T 的类型(在本例中为 SuperClass),然后使用虚拟分派为对象方法的调用提供差异,并使用静态分派为静态方法的调用提供差异。

因此,当您执行 Dummy.print() 时,编译器不会在 中将 T 全局替换为 SubClass虚拟。 编译器所做的只是检查 Dummy 方法中使用 T 作为参数或返回类型是否是 SubClassDummy 内部的任何代码都没有改变,因此无论 T 是什么,都会调用相同的 SuperClass 静态方法。

如果您希望根据参数化类型在泛型类中实现不同的行为,则可以传入该类型的对象并使用虚拟方法,或者传入该类型的类并使用反射。

Unlike C++ templates, Java generics work by type erasure, so it only generates one class for all values of T, and translates all references to type T in this class to the super type of T, in this case SuperClass, then uses virtual dispatch to provide the variance for calls to object methods, and static dispatch to calls to static methods.

So when you do Dummy<SubClass>.print(), the compiler does not make a global replace of T with SubClass in Dummy. All the compiler does is check that uses of T as an argument or return type in the methods of Dummy are SubClass. There's no change to any code inside Dummy, so the same SuperClass static method gets called whatever T is.

If you want different behaviour in a generic class depending on the parameterised type, you have pass an object of that type in and use a virtual method, or pass in the class for the type and use reflection.

秉烛思 2024-07-22 20:21:18

当您使用“new Dummy()”实例化该类时,您调用了默认构造函数,该构造函数实际上并未设置任何内容。
当 print 方法被调用时,VM 发现 T 的类型(如类声明中所声明的)是 SuperClass; 然后它调用该类的静态方法。

When you instanciated the class with "new Dummy()" you called the default constructor which doesn't actually set anything.
When print method got called, the VM saw that the type of T, as declared in the class declaration, is SuperClass; It then calls the static method on this class.

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