Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java编译器不允许我返回泛型类型?_Java_Generics - Fatal编程技术网

为什么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来阻止示例代码