我很确定有人问过类似的问题,但我真的找不到确切的措辞,所以就去了。
如果我有这三个班级:
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
方法中不兼容?
答案 0 :(得分:2)
您通过将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();
}
答案 1 :(得分:1)
问题在于,您可以在扩展了ClassA
的另一个类中存储ClassC
例如,您有一个ClassA
与ClassB
一样扩展了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 { }
}
实例?这就是为什么你不能
(defrule accept-location-lessthan-path
(or (geological-survey-lessthan-path-is stable) (geological-survey-lessthan-path-is Stable))
=>
(if (production-is medium)
then
(assert (medium-outcome))
(printout t "Second best "crlf)
else
(if (production-is high)
(assert (ideal-location))
(printout t "
Accepted! The location is ideal; you can start building now! :) " crlf))))
答案 2 :(得分:1)
这是因为T
可以是ClassA
的任何子类。举例说明,假设您还有一个扩展了ClassC
ClassA
class ClassC extends ClassA {
}
现在,您永远无法确定将使用ClassA
的哪个子类来调用此方法。
class Factory {
public <T extends ClassA> T create() {
return new ClassB();
}
}
这里T
可能是ClassB
,ClassC
等。因此,您不可能返回{的一个可能的子类之一{1}}
详细信息可在此SO question中找到。