Java Generics返回类型问题

Cli*_*ote 14 java generics

我有以下方法:

public <T extends Result> T execute(Command<T> command)
{
     return new LoginResult();
}
Run Code Online (Sandbox Code Playgroud)

Result是一个接口,该类LoginResult确实实现了这个接口.但是,我收到错误:

不兼容的类型,必需:T,found:com.foo.LoginResult

然而,如果我将方法签名更改为:

public Result execute(Command<T> command)
Run Code Online (Sandbox Code Playgroud)

然后相同的返回线工作正常,没有任何错误.

这是什么问题?我怎么LoginResult能从这个方法回来?

编辑:我想使用泛型的原因是,我可以做如下的事情:

Command<LoginResult> login = new Command<>();
 LoginResult result = execute( login );
Run Code Online (Sandbox Code Playgroud)

Sim*_*onC 16

您不能这样做,因为编译器无法确认LoginResult是否为类型T,因为它是在调用站点推断的(即调用者决定将使用哪个类型参数).

  • @ClickUpvote因为`<T extends Result>`并不意味着"任何扩展Result的类".它意味着"扩展Result的特定类,但我们不知道该类是什么". (13认同)

Cos*_*atu 6

要回答您编辑过的问题,

没有明确的演员表就无法做到这一点。因此,最简单(但仍然很残酷)的解决方案是:

public <T extends Result> T execute(Command<T> command) {
    return (T) new LoginResult();
}
Run Code Online (Sandbox Code Playgroud)

但是这样一来,您将为正确的命令实例化正确的结果承担全部责任,因为编译器将不再为您提供帮助。

唯一可以帮助您动态实例化事物的方法是对实际的引用Class<T>

因此,如果Class<T> getResultType()在命令中添加类似的方法,则可以编写:

return command.getResultType().newInstance(); // instead of new SpecificResult()
Run Code Online (Sandbox Code Playgroud)

当然,这意味着每个Result实现中都有一个默认构造函数,依此类推...

面向对象的更友好的方法(无反射)是让命令实例化其自身的结果(使用factory方法T instantiateResult()):

return command.instantiateResult();
Run Code Online (Sandbox Code Playgroud)