我试图使用注释处理器来生成特定工厂接口的实现。这些接口如下所示:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
和
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
注释处理器正在做正确的事情,并为每个匹配的类生成一个工厂,该工厂用相应的注释进行注释。
注释处理器的输出如下所示:
public final class TestViewImplFactory implements ViewFactory {
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
以及相应的其他类:
public final class TestPresenterImplFactory implements PresenterFactory {
public final TestPresenter create() {
return new TestPresenterImpl();
}
}
但是不能编译TestViewImFactory。错误消息是:
“类'TestViewImplFactory'必须声明为抽象或在'ViewFactory'中实现抽象方法创建”
Java说,以下是正确的:
@Override
public View create(Presenter presenter) {
return new TestViewImpl(presenter);
}
考虑到用户想要知道返回哪个视图以及需要哪个演示者,这根本不起作用。我原以为:
因为他们俩真的很相似。我以为第一个是真的。
我错过了什么?
如果将泛型类型添加到TestViewImplFactory,如下所示:
public final class TestViewImplFactory implements ViewFactory<TestView> {
@Override
public <S extends Presenter<TestView>> TestView create(S presenter) {
return new TestViewImpl(presenter);
}
}
问题出现了,构造函数参数(类型TestPresenter的)是不正确的。将S更改为具体的TestPresenter将再次使类不可编译,原因与上述相同。
所以,我偶然发现了一个可以编译的“解决方案”。
基本上必须做的是将ViewFactory界面更改为以下内容:
public interface ViewFactory<T extends View, S extends Presenter<T>> {
T create(S presenter);
}
因此,类定义与上述问题中的方法具有相同的泛型类型。
编译后(这次使用泛型类型规范),输出如下所示:
public final class TestViewImplFactory implements ViewFactory<TestView, TestPresenter> {
public TestViewImplFactory() {
}
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
这可以被编译并成功运行。
然而,这并不能回答原来的问题。为什么类型定义中显式声明的泛型正确,而方法声明中继承和指定的泛型错误且不可编译?
具体来说:为什么Java可以自动继承一个泛型(在PresenterFactory中),而其他泛型(在ViewFactory中、方法和类型声明中)呢?
我认为您的问题声明的第一部分应该得到解决,因为我注意到您的注释处理器正在实现原始的ViewFactory类型。我想使用类型擦除,因为它是生成的代码,所以在实践中没有真正的区别。但是如果处理器可以使用参数化类型生成实现,那么至少更容易推理这个问题。
因此,给定消息签名
public class TestViewImplFactory implements ViewFactory<TestView> {
@Override
public <S extends Presenter<TestView>> TestView create(S presenter) { ... }
}
或者更简单地说:
public class TestViewImplFactory implements ViewFactory<TestView> {
@Override
public TestView create(Presenter presenter) { ... }
}
但是,使用其中任何一个,都不能将参数限制为
TestPresenter
。您必须将ViewFactory
更改为以下内容
public interface ViewFactory<T extends View, U extends Presenter<T>>
它们实现了
ViewFactory
为什么它不起作用:
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
此签名导致编译器在调用create()
的位置推断S
<代码>S将是您分配给的create()
,如:
FancyPresenter fp = presenterFactory.create();
SomeOtherPresenter sop = presenterFactory.create();
这意味着:
public TestPresenter create(){...}
不是以下内容的实现:
<S extends Presenter<T>> S create();
但是方法重写。没有接口方法的实现。甚至不可能用具体的S
提供任何实现。它类似于:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
在这里,泛型再次被推断为方法调用。所以一个实现必须接受每个子类型的Presenter
public interface ViewFactory<T extends View> {
T create(Presenter<T> presenter);
}
但是返回类型依赖于参数
演示者
。如果演示者
为您提供了一个仅创建T
实例的方法,这可能会起作用。
为什么其他解决方案有效:
通过类型绑定方法的泛型意味着接口的实现提供了具体的类型。因此,对于一个对象,您不需要提供多个不同的绑定。无论您在哪里调用
PresentFactory的
创建()
方法
我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?
使用Java注释处理器,我有以下类型: 并且: 我有的为: 现在我想获取类型参数<code>的TypeElement 我试过了: 当我打印时,我得到而不是。 如何从TypeParameter中获取真正的StartPagePresenter?
我正试图使Filepond工作,但CSS中的这一行似乎破坏了它-在ul选择器中。 我试着对页面的整个部分进行核化,直到Filepond起作用,将目标锁定在css上,最后在ul{}中找到前面提到的行。我可以把其他的东西都抹掉,只留下那条线,而文件孔仍然坏了,所以我肯定这是问题所在,但我不知道是怎么回事。 我尝试使用Chrome的检查器功能查看运行时页面源代码,但在那里找不到溢出。 然后我使用Note
我试图使用IntelliJ2017 Ultimate构建/运行一个使用MapStruct的Spring Boot应用程序。这是一个分级项目。我的问题是IntelliJ似乎没有运行MapStruct注释处理器。我意识到我可以配置IntelliJ来委托Gradle构建过程(请参见此),但我希望简单地配置IntelliJ来使用APT来生成必要的类本身。 我已经为我的项目启用了APT,但是我的类仍然没有生
目前,我们所有的构建都失败了,因为无法从公共SBT插件回购中解析插件。我们得到以下错误: [警告]注意:某些未解析的依赖项具有额外属性。检查这些依赖项是否与请求的属性一起存在。[警告]com。类型安全。播放:sbt插件:2.4。0(scalaVersion=2.10,sbtVersion=0.13)[警告]com。github。gseitz:sbt版本:1.0。0(标度规避=2.10,sbtVer
需要注释处理器的帮助。我创建了一个简单的注释处理器,它使用@autoservice注释来检查注释的字段是否为最终字段。但它没有显示任何编译时错误。这是我的配置 注释: 注释处理器: pom文件: 测试文件: