我很确定有人问过这样的问题,但我真的找不到确切的措辞,所以就这样吧。
如果我有这三个类:
package boundedtypetest;
public class Factory {
private class ClassA {}
private class ClassB extends ClassA {}
public <T extends ClassA> T create() {
return new ClassB();
}
}
为什么Java编译器说T
和ClassB
在create
方法中不兼容?
通过将T
声明为具有上界的类型参数,您创建了一个泛型方法。对于泛型方法,您必须知道,调用者可以通过向方法传递显式类型参数来决定什么是T
。
class ClassC extends ClassA {}
ClassC c = new Factory().<ClassC>create();
不能保证调用者显式或隐式选择的类型参数将与返回的类型匹配,并且您返回的是ClassB
。编译器不能保证这里的类型安全,因此这是不允许的。
如果不需要泛型,请从方法中移除类型参数,并声明create
以返回ClassB
、ClassA
或Object
。
如果您需要泛型,那么您必须获取类型为Class<T>
的参数,并用它创建一个实例以满足编译器的要求。
public <T extends ClassA> T create(Class<T> clazz) throws ReflectionRelatedExceptions
{
return clazz.getConstructor().newInstance();
}
问题是您将能够将ClassB
存储在另一个扩展ClassA
的类中
例如,您有一个ClassC
,它与ClassB
一样扩展了ClassA
,您可以将create()
的结果存储在ClassC
对象中,但该方法能够返回ClassB
实例?这就是为什么你不能
class Factory {
void method() {
ClassC c = create(); //This is correct, regarding the return type of the method
} // But it would allow to store ClassB in ClassC : NOPE
public <T extends ClassA> T create() {
return new ClassB();
}
private class ClassA { }
private class ClassB extends ClassA { }
private class ClassC extends ClassA { }
}
T
可以是ClassA
的任何子类。举例来说,假设您有另一个扩展ClassA
的类ClassC
class ClassC extends ClassA {
}
现在,您永远无法确定ClassA
的哪个子类将用于调用此方法。
class Factory {
public <T extends ClassA> T create() {
return new ClassB();
}
}
这里的T
可以是ClassB
、ClassC
等。因此,您不可能返回ClassA
的一个可能的子类
详细信息可在此SO问题中找到。