类从泛型超类扩展但不指定泛型类型

时间:2014-01-09 07:29:22

标签: java generics

我编写了一个通用的抽象类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;
            }
        });
    }
}

在这种情况下如何解释泛型类型?

1 个答案:

答案 0 :(得分:2)

第一期:

由于您要扩展原始类型TestSuper,因此您获得的execute方法将是在类型擦除后获得的方法。所以,方法签名真的是这样的:

public Object execute(Callable callable)

在类型擦除期间,类型参数被替换为最接近的边界。因为,类型参数是<T>而没有任何绑定,所以最接近的边界被视为Object。这就是为什么你得到编译错误,因为编译器看到execute方法的返回类型为Object,并且你将结果存储在Boolean类型中。实际上,您应该只在@Override注释中遇到编译器错误,因为您的callExecute方法没有覆盖超类中的方法。返回类型应为Object,而不是void

当然,当您将Boolean result更改为Object result时,它会起作用。

请参阅JLS §4.8 - Raw Types

  

构造函数的类型(第8.8节),实例方法(第8.4节,第9.4节),或者   非静态字段(第8.3节)未从中继承的原始类型C的M.   它的超类或超接口是对应的原始类型   在相应的通用声明中擦除其类型   下进行。


因此,在第二种情况下,由于您要扩展参数化类型TestSuper<Object>,因此execute方法现在只是通用方法。因此,类型T被推断为Boolean