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 编译器说 T
和 ClassB
在 create
方法中不兼容?
问题是您可以将 ClassB
存储在另一个扩展 ClassA
的 class 中
例如,你有一个 ClassC
扩展 ClassA
与 ClassB
相同,你可以将 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
可能是ClassB
、ClassC
等。因此您不可能return其中一个可能的子-classes of ClassA
详细信息可以在这个SO question.
中找到
您已通过将 T
声明为具有上限的类型参数来创建泛型方法。对于泛型方法,您必须知道调用者可以通过将显式类型参数传递给您的方法来决定 T
是什么。
class ClassC extends ClassA {}
ClassC c = new Factory().<ClassC>create();
无法保证调用者选择的类型参数(显式或隐式)将与 returned 的类型相匹配,而您正在 returning ClassB
.编译器不能保证这里的类型安全,所以这是不允许的。
如果您不需要泛型,请从方法中删除类型参数并声明 create
到 return 一个 ClassB
、ClassA
或 Object
.
如果您需要泛型,那么您必须采用 Class<T>
类型的参数并使用它创建一个实例以满足编译器的要求。
public <T extends ClassA> T create(Class<T> clazz) throws ReflectionRelatedExceptions
{
return clazz.getConstructor().newInstance();
}
我很确定有人问过这样的问题,但我真的找不到确切的措辞,所以就这样吧。
如果我有这三个类:
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
方法中不兼容?
问题是您可以将 ClassB
存储在另一个扩展 ClassA
例如,你有一个 ClassC
扩展 ClassA
与 ClassB
相同,你可以将 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
ClassC
class ClassC extends ClassA {
}
现在您永远无法确定 ClassA
的哪个子 class 将用于调用此方法。
class Factory {
public <T extends ClassA> T create() {
return new ClassB();
}
}
此处T
可能是ClassB
、ClassC
等。因此您不可能return其中一个可能的子-classes of ClassA
详细信息可以在这个SO question.
中找到您已通过将 T
声明为具有上限的类型参数来创建泛型方法。对于泛型方法,您必须知道调用者可以通过将显式类型参数传递给您的方法来决定 T
是什么。
class ClassC extends ClassA {}
ClassC c = new Factory().<ClassC>create();
无法保证调用者选择的类型参数(显式或隐式)将与 returned 的类型相匹配,而您正在 returning ClassB
.编译器不能保证这里的类型安全,所以这是不允许的。
如果您不需要泛型,请从方法中删除类型参数并声明 create
到 return 一个 ClassB
、ClassA
或 Object
.
如果您需要泛型,那么您必须采用 Class<T>
类型的参数并使用它创建一个实例以满足编译器的要求。
public <T extends ClassA> T create(Class<T> clazz) throws ReflectionRelatedExceptions
{
return clazz.getConstructor().newInstance();
}