返回边界类型与匹配边界的类型不兼容

时间:2018-12-12 16:51:05

标签: java generics bounded-types

我很确定有人问过类似的问题,但我真的找不到确切的措辞,所以就去了。

如果我有这三个班级:

package boundedtypetest;

public class Factory {
    private class ClassA {}

    private class ClassB extends ClassA {}

    public <T extends ClassA> T create() {
        return new ClassB();
    }
}

为什么Java编译器会说TClassBcreate方法中不兼容?

3 个答案:

答案 0 :(得分:2)

您通过将T声明为具有上限的类型参数来创建了通用方法。使用泛型方法,您必须意识到调用者可以通过将显式类型参数传递给您的方法来确定T是什么。

class ClassC extends ClassA {}

ClassC c = new Factory().<ClassC>create();

不能保证调用者选择的类型参数(显式或隐式)将与返回的类型匹配,并且您将返回ClassB。编译器在这里不能保证类型安全,因此是不允许的。

如果不需要泛型,请从方法中删除类型参数,并声明create以返回ClassBClassAObject

如果需要泛型,则必须采用Class<T>类型的参数,并使用它创建一个实例来满足编译器的要求。

public <T extends ClassA> T create(Class<T> clazz) throws ReflectionRelatedExceptions 
{
    return clazz.getConstructor().newInstance();
}

答案 1 :(得分:1)

问题在于,您可以在扩展了ClassA的另一个类中存储ClassC

例如,您有一个ClassAClassB一样扩展了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可能是ClassBClassC等。因此,您不可能返回{的一个可能的子类之一{1}}

详细信息可在此SO question中找到。