我编写了一个通用的抽象类TestSuper,值得注意的是它有一个带有param Callable的方法“execute”,Callable的泛型类型是T,而T与V无关。 这是代码:
//my abstract class
public abstract class TestSuper<V>
{
public abstract void callExecute(V value);
public <T> T execute(Callable<T> callable)
{
T call = null;
try
{
call = callable.call();
}
catch (Exception e)
{
e.printStackTrace();
}
return call;
}
}
然后我写这样的子类:
//the sub class that not specify the generic type from TestSuper
public class TestSub extends TestSuper
{
@Override
public void callExecute(Object value)
{
Boolean result = execute(new Callable<Boolean>()
{
@Override
public Boolean call() throws Exception
{
return Boolean.TRUE;
}
});
}
}
我对变量“result”的类型感到困惑,因为这段代码带有编译时错误。 像这样:
java: incompatible types
required: java.lang.Boolean
found: java.lang.Object
如果我将“布尔结果”替换为“对象结果”,则错误消失。
如果我在测试TestSub时指定泛型类型,也没有错误。
public class TestSub extends TestSuper<Object>
{
@Override
public void callExecute(Object value)
{
Boolean result = execute(new Callable<Boolean>()
{
@Override
public Boolean call() throws Exception
{
return Boolean.TRUE;
}
});
}
}
在这种情况下如何解释泛型类型?
答案 0 :(得分:2)
第一期:
由于您要扩展原始类型TestSuper
,因此您获得的execute
方法将是在类型擦除后获得的方法。所以,方法签名真的是这样的:
public Object execute(Callable callable)
在类型擦除期间,类型参数被替换为最接近的边界。因为,类型参数是<T>
而没有任何绑定,所以最接近的边界被视为Object
。这就是为什么你得到编译错误,因为编译器看到execute
方法的返回类型为Object
,并且你将结果存储在Boolean
类型中。实际上,您应该只在@Override
注释中遇到编译器错误,因为您的callExecute
方法没有覆盖超类中的方法。返回类型应为Object
,而不是void
。
当然,当您将Boolean result
更改为Object result
时,它会起作用。
构造函数的类型(第8.8节),实例方法(第8.4节,第9.4节),或者 非静态字段(第8.3节)未从中继承的原始类型C的M. 它的超类或超接口是对应的原始类型 在相应的通用声明中擦除其类型 下进行。
因此,在第二种情况下,由于您要扩展参数化类型TestSuper<Object>
,因此execute
方法现在只是通用方法。因此,类型T
被推断为Boolean
。