Tho*_*uck 20 java generics annotations annotation-processing
我试图使用Annotation Processors来生成特定Factory接口的实现.这些接口看起来如下:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
Run Code Online (Sandbox Code Playgroud)
和
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
Run Code Online (Sandbox Code Playgroud)
Annotation Processor正在执行正确的操作,并为每个匹配的类生成一个工厂,该工厂使用相应的注释进行注释.
注释处理器的输出如下:
public final class TestViewImplFactory implements ViewFactory {
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
Run Code Online (Sandbox Code Playgroud)
和相应的其他类:
public final class TestPresenterImplFactory implements PresenterFactory {
public final TestPresenter create() {
return new TestPresenterImpl();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,TestViewImplFactory无法编译.错误消息是:
"类'TestViewImplFactory'必须声明为abstract或在'ViewFactory'中实现抽象方法create(S)"
Java说,以下是正确的:
@Override
public View create(Presenter presenter) {
return new TestViewImpl(presenter);
}
Run Code Online (Sandbox Code Playgroud)
考虑到用户想要知道哪些View将被返回以及需要哪个Presenter,这根本不起作用.我原以为:
因为他们两个都很相似 我预计第一个是真的.
我在这里错过了什么?
如果我将Generic类型添加到TestViewImplFactory,如下所示:
public final class TestViewImplFactory implements ViewFactory<TestView> {
@Override
public <S extends Presenter<TestView>> TestView create(S presenter) {
return new TestViewImpl(presenter);
}
}
Run Code Online (Sandbox Code Playgroud)
问题出现了,构造函数Parameter(类型为TestPresenter)不正确.将S更改为具体的TestPresenter将再次使该类无法编译,原因与上述相同.
所以,我偶然发现了一个可以编译的"解决方案".
基本上要做的是将ViewFactory接口更改为以下内容:
public interface ViewFactory<T extends View, S extends Presenter<T>> {
T create(S presenter);
}
Run Code Online (Sandbox Code Playgroud)
因此,类定义具有与上述问题中的方法相同的通用类型.
在编译之后(这次使用泛型类型规范),输出如下所示:
public final class TestViewImplFactory implements ViewFactory<TestView, TestPresenter> {
public TestViewImplFactory() {
}
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
Run Code Online (Sandbox Code Playgroud)
这可以编译并成功运行.
然而,这并不回答原始问题.为什么在类型定义中明确声明的泛型是正确的,但在方法声明中继承和指定错误且不可编译?
具体来说:为什么Java可以自动(在PresenterFactory中)继承一个Generic而不在(在ViewFactory中,在方法和类型声明中)继承一个Generic?
Tri*_*ova 15
为什么它不起作用:
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
Run Code Online (Sandbox Code Playgroud)
此签名使编译器S在create()调用的位置进行推断.S将是你所分配create()的:
FancyPresenter fp = presenterFactory.create();
SomeOtherPresenter sop = presenterFactory.create();
Run Code Online (Sandbox Code Playgroud)
这意味着:
public TestPresenter create(){...}
Run Code Online (Sandbox Code Playgroud)
不是以下的实现:
<S extends Presenter<T>> S create();
Run Code Online (Sandbox Code Playgroud)
但方法覆盖.没有实现接口的方法.甚至不可能提供具体的任何实现S.它类似于:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
Run Code Online (Sandbox Code Playgroud)
这里再次推断出方法调用的泛型.因此,实现必须接受每个子类型Presenter<T>.唯一有效的实现是:
public interface ViewFactory<T extends View> {
T create(Presenter<T> presenter);
}
Run Code Online (Sandbox Code Playgroud)
但返回类型取决于参数presenter.如果presenter为您提供T仅创建实例的方法,则可能会有效.
为什么其他解决方案有效:
通过类型绑定方法的泛型意味着接口的实现提供了具体类型.因此,对于一个对象,您不需要提供多个不同的绑定.无论你在哪里调用返回类型的create()方法,PresenterFactory<TestView, TestPresenter<TestView>>泛型都是绑定的TestPresenter<TestView>.因此,每个子类型都有可能的实现PresenterFactory<...>.