【问题标题】:a class extends from generic super class but not specify the generic type一个类从泛型超类扩展,但未指定泛型类型
【发布时间】:2014-01-09 19:06:36
【问题描述】:

我写了一个泛型抽象类TestSuper,值得注意的是它有一个方法“execute”,参数为Callable,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;
            }
        });
    }
}

我对变量“结果”的类型感到困惑,因为此代码带有编译时错误。 像这样:

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;
            }
        });
    }
}

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

【问题讨论】:

标签: java generics


【解决方案1】:

第一期:

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

public Object execute(Callable callable)

在类型擦除期间,类型参数被替换为其最近的边界。因为,类型参数是&lt;T&gt;,没有任何界限,最近的界限被认为是Object。这就是为什么,您会收到编译错误,因为编译器看到返回类型为Objectexecute 方法,并且您将结果存储在Boolean 类型中。实际上,您应该只在 @Override 注释处遇到编译器错误,因为您的 callExecute 方法没有覆盖超类中的方法。返回类型应该是Object 而不是void

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

JLS §4.8 - Raw Types:

构造函数的类型(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或 非继承自原始类型 C 的非静态字段(第 8.3 节)M 它的超类或超接口是对应的原始类型 在对应的泛型声明中擦除其类型 C.


所以,在第二种情况下,由于您正在扩展参数化类型TestSuper&lt;Object&gt;execute 方法现在将只是泛型方法。因此,T 类型被推断为Boolean

【讨论】:

  • +1 很好的解释 Rohit。尤其是 JLS 参考,它也为我清除了一件事情 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多