我有以下方法:
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
,因为它是在调用站点推断的(即调用者决定将使用哪个类型参数).
要回答您编辑过的问题,
没有明确的演员表就无法做到这一点。因此,最简单(但仍然很残酷)的解决方案是:
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)