为什么Java编译器不允许我返回泛型类型?
我对泛型有点不知所措。我有以下代码:为什么Java编译器不允许我返回泛型类型?,java,generics,Java,Generics,我对泛型有点不知所措。我有以下代码: public interface SampleValue<T> { T getValue(); } public static class SampleBoolean implements SampleValue<Boolean> { @Override public Boolean getValue() { return Boolean.TRUE; } } public stati
public interface SampleValue<T> {
T getValue();
}
public static class SampleBoolean implements SampleValue<Boolean> {
@Override
public Boolean getValue() {
return Boolean.TRUE;
}
}
public static final class SampleValueGenerator {
private SampleValueGenerator() {
// do not call
}
public static <T, R extends SampleValue<T>> R forType(Class<T> clazz) {
if(Boolean.class.equals(clazz)) {
return new SampleBoolean();
}
}
}
公共接口采样值{
T getValue();
}
公共静态类SampleBoolean实现SampleValue{
@凌驾
公共布尔getValue(){
返回Boolean.TRUE;
}
}
公共静态最终类SampleValueGenerator{
私有SampleValueGenerator(){
//不要打电话
}
公共静态R forType(clazz类){
if(Boolean.class.equals(clazz)){
返回新的SampleBoolean();
}
}
}
当我尝试此操作时,IntelliJ(即编译器)告诉我R
和SampleBoolean
是不兼容的类型(对于返回
行)
当我尝试非泛型(原始)返回类型时
type(Class clazz)的公共静态样本值{
我没有得到任何错误
publicstatic返回的R始终是一个实现布尔值SampleValue的R,而不是一个实现T(在运行时设置的泛型类型)SampleValue的R
//如果我这样做
SampleValueGenerator.forType(Integer.class)
//我期待实现SampleValue的东西
//但您总是返回实现SampleValue的内容
编辑这应该可以工作(尚未测试)
publicstaticrfortype(类clazz){
返回()->{
试一试{
return(T)clazz.newInstance();//clazz还应该有一个默认构造函数。
}捕获(例外e){
//此catch块应用于NoSuchMethodException和InstanceException
}
}
}
返回的R始终是实现布尔值的SampleValue的R,而不是实现T(在运行时设置的泛型类型)的SampleValue的R
//如果我这样做
SampleValueGenerator.forType(Integer.class)
//我期待实现SampleValue的东西
//但您总是返回实现SampleValue的内容
编辑这应该可以工作(尚未测试)
publicstaticrfortype(类clazz){
返回()->{
试一试{
return(T)clazz.newInstance();//clazz还应该有一个默认构造函数。
}捕获(例外e){
//此catch块应用于NoSuchMethodException和InstanceException
}
}
}
我认为问题在于SampleBoolean
实现了SampleValue
,这是一种特定类型,而不是泛型。另一方面,R被声明为扩展泛型类型SampleValue
SampleValue
和SampleValue
是两种不同的类型,因此会出现编译错误。forType
函数希望返回泛型类型R,并使用以下语句返回特定类型:
return new SampleBoolean();
我认为问题在于SampleBoolean
实现了SampleValue
,这是一种特定类型,而不是泛型。另一方面,R被声明为扩展泛型类型SampleValue
SampleValue
和SampleValue
是两种不同的类型,因此会出现编译错误。forType
函数希望返回泛型类型R,并使用以下语句返回特定类型:
return new SampleBoolean();
原因是您的条件没有向编译器证明任何东西
您在这里遇到的困惑涉及到您的条件:
if(Boolean.class.equals(clazz))
通过此检查,您可以推断T
是一个Boolean
,但编译器无法强制执行此检查。编译器不会隐式假设此检查将确保T
是Boolean
。(在该方法的上下文中,编译器所知道的关于equals
的所有信息是它返回一个布尔值
)
因此,尽管您进行了检查,R
和SampleBoolean
是不兼容的类型,因为R扩展了SampleValue
,而T
可以是任何类型
我真的想不出一个方法来确保基于t
返回new SampleValue
,但是如果我这样做了,我会用一个解决方案来编辑这个答案。我希望看到其他人对此的想法。原因是你的条件没有向编译器证明任何东西
您在这里遇到的困惑涉及到您的条件:
if(Boolean.class.equals(clazz))
通过此检查,您可以推断T
是一个Boolean
,但编译器无法强制执行此检查。编译器不会隐式假设此检查将确保T
是Boolean
。(在该方法的上下文中,编译器所知道的关于equals
的所有信息是它返回一个布尔值
)
因此,尽管您进行了检查,R
和SampleBoolean
是不兼容的类型,因为R扩展了SampleValue
,而T
可以是任何类型
我真的想不出一个方法来确保返回基于t
的new SampleValue
,但如果我这样做了,我会用一个解决方案编辑这个答案。我希望看到其他人对此的想法。他的接口是一个功能接口,可能可以使用lambdas,然后使用claz.newInstance()通过反射创建一个类型t,唯一的缺点是,如果没有默认构造函数,则需要处理异常。他的接口是函数接口,可能可以使用lambdas,然后使用clazz.newInstance()通过反射创建类型T,唯一的缺点是,如果没有默认构造函数,则需要处理异常。可以通过声明一个类AnotherSampleBoolean实现SampleValue{…}
,然后调用AnotherSampleBoolean result=forType(Boolean.class)
R
将推断为a来阻止示例代码