Return 绑定类型与匹配绑定的类型不兼容

Return bounded type is incompatible with a type that matches the bound

我很确定有人问过这样的问题,但我真的找不到确切的措辞,所以就这样吧。

如果我有这三个类:

package boundedtypetest;

public class Factory {
    private class ClassA {}

    private class ClassB extends ClassA {}

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

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

问题是您可以将 ClassB 存储在另一个扩展 ClassA

的 class 中

例如,你有一个 ClassC 扩展 ClassAClassB 相同,你可以将 create() 的结果存储在 ClassC 对象中,但该方法能够 return 一个 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 的任何子 class。为了说明,假设您有另一个扩展 ClassA

的 class ClassC
class ClassC extends ClassA {
}

现在您永远无法确定 ClassA 的哪个子 class 将用于调用此方法。

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

此处T可能是ClassBClassC等。因此您不可能return其中一个可能的子-classes of ClassA

详细信息可以在这个SO question.

中找到

您已通过将 T 声明为具有上限的类型参数来创建泛型方法。对于泛型方法,您必须知道调用者可以通过将显式类型参数传递给您的方法来决定 T 是什么。

class ClassC extends ClassA {}

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

无法保证调用者选择的类型参数(显式或隐式)将与 returned 的类型相匹配,而您正在 returning ClassB.编译器不能保证这里的类型安全,所以这是不允许的。

如果您不需要泛型,请从方法中删除类型参数并声明 create 到 return 一个 ClassBClassAObject.

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

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