5

我有以下代码:

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。还是静态函数调用对泛型引用无效?

提前非常感谢!

4

3 回答 3

13

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

如果你说:

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

您还将获得“超级”。没有“多态”静态方法。

在您的情况下,编译器所知道T的只是它 extends SuperClass,所以它会调用SuperClass.getName().

于 2009-03-24T12:55:22.967 回答
1

与 C++ 模板不同,Java 泛型通过类型擦除来工作,因此它只为 的所有值生成一个类T,并将该类中对类型的所有引用转换T为 的超类型T,在这种情况下SuperClass,然后使用虚拟调度来为对对象方法的调用,以及对静态方法的调用的静态分派。

因此,当您这样做时Dummy<SubClass>.print(),编译器不会对Twith SubClassin进行全局替换Dummy。编译器所做的只是检查在areT的方法中作为参数或返回类型的使用。里面的任何代码都没有变化,所以不管是什么,都会调用相同的静态方法。DummySubClassDummySuperClassT

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

于 2009-03-24T13:10:11.247 回答
0

当你用“new Dummy()”实例化这个类时,你调用了默认构造函数,它实际上并没有设置任何东西。当调用 print 方法时,VM 看到 T 的类型,正如在类声明中声明的那样,是 SuperClass;然后它调用这个类的静态方法。

于 2009-03-24T13:00:09.197 回答