无法对通用子类进行静态引用 (Java)
我有以下代码:
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。 或者静态函数调用对于泛型引用无效吗?
预先非常感谢!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这不仅仅是一个关于泛型的问题。
如果你说:
你也会得到“超级”。 不存在“多态”静态方法。
在您的情况下,编译器对
T
的了解就是它扩展了SuperClass
,因此它将调用SuperClass.getName()
。This isn't just an issue about generics.
If you say:
you will also get "super". There are no "polymorphic" static methods.
In your case, all the compiler knows about
T
is that it extendsSuperClass
, so it will callSuperClass.getName()
.与 C++ 模板不同,Java 泛型通过类型擦除来工作,因此它只为
T
的所有值生成一个类,并将该类中对类型T
的所有引用转换为超类T
的类型(在本例中为SuperClass
),然后使用虚拟分派为对象方法的调用提供差异,并使用静态分派为静态方法的调用提供差异。因此,当您执行
Dummy.print()
时,编译器不会在中将
。 编译器所做的只是检查T
全局替换为SubClass
虚拟Dummy
方法中使用T
作为参数或返回类型是否是SubClass
。Dummy
内部的任何代码都没有改变,因此无论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 typeT
in this class to the super type ofT
, in this caseSuperClass
, 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 ofT
withSubClass
inDummy
. All the compiler does is check that uses ofT
as an argument or return type in the methods ofDummy
areSubClass
. There's no change to any code insideDummy
, so the sameSuperClass
static method gets called whateverT
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.
当您使用“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.