假设我有一个通用类:
public class GClass implements GInterface<Impl> {
// other code
@Override
public Class<SomeClass> getType() {
return SomeClass.class
}
}
实现接口:
public interface GInterface<T extends OtherClass> {
// other code
return Class<SomeClass> getType();
}
然后我调用 getType():
GInterface<?> gi = getInstance();
Class<SomeClass> type = gi.getType(); // <- gives warning
我在这里收到警告有何意义?
getType()
的结果不是泛型的(它不使用泛型类型参数 T),而是静态定义为 Class<SomeClass>
。因此编译器应该知道 Class<SomeClass> type = gi.getType()
是 100% 安全的,对吗?
我错过了什么吗?
我希望调用:
Class<SomeClass> type = gi.getType()
不会生成任何警告。
在 Java 中,泛型类型是不变的,这意味着即使 SomeClass 是
OtherClass
的子类型,Class<SomeClass>
也不是 Class<OtherClass>
的子类型。这就是为什么您不能在没有警告的情况下直接将 gi.getType()
返回 Class<SomeClass>
分配给 Class<OtherClass>
类型的变量。
但是,您提供的代码片段包含一些不一致的地方,无法按原样编译。
getType
中的GInterface
方法应该有一个与其定义一致的返回类型。
这是根据您提供的内容进行更正的版本:
public interface GInterface<T extends OtherClass> {
Class<? extends OtherClass> getType();
}
public class GClass extends OtherClass implements GInterface<SomeClass> {
@Override
public Class<SomeClass> getType() {
return SomeClass.class;
}
}
在上面的代码中,
GInterface
中的getType返回一个代表OtherClass
子类的Class对象。当您重写 GClass
中的 getType 时,您可以指定确切的子类,在本例中为 SomeClass。
现在,当你调用 getType 时:
GInterface<?> gi = getInstance(); // Assuming getInstance() is defined elsewhere and returns an instance of GClass
Class<? extends OtherClass> type = gi.getType(); // This should not give a warning
在这种情况下,
Class<? extends OtherClass>
告诉编译器您期望一个代表OtherClass的某个子类的Class对象,但您没有指定它是什么子类。由于 SomeClass
是 OtherClass
的子类,因此该分配是安全的,并且不应该出现警告。
如果您看到警告,可能是因为
getInstance()
的定义方式或此处未显示的其他代码。上面更正的代码不应针对将 gi.getType()
分配给类型变量产生警告。如果 getInstance()
返回 GInterface,则意味着类型参数未知,因此 getType()
的返回类型在编译时也将是未知的,即使该方法的签名表明它将返回代表某个子类的 Class 对象OtherClass
。
如果您控制
GInterface
并且您确定 getType 将始终返回 Class<SomeClass>
,您可以像这样定义 GInterface 以避免警告:
public interface GInterface<T extends OtherClass> {
Class<T> getType();
}
然后,在实现这个接口的时候,指定具体的类型:
public class GClass implements GInterface<SomeClass> {
@Override
public Class<SomeClass> getType() {
return SomeClass.class;
}
}
这样,
GInterface
中的方法签名使用泛型类型参数T,并且实现类GClass
指定T是SomeClass
。这应该可以消除调用 getType 时与类型安全相关的任何警告。