gpt4 book ai didi

java - 注释处理器似乎破坏了 Java 泛型

转载 作者:IT老高 更新时间:2023-10-28 20:54:05 24 4
gpt4 key购买 nike

背景

我试图使用注释处理器来生成特定工厂接口(interface)的实现。这些界面如下所示:

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

但是无法编译 TestViewImplFactory。错误信息是:

"Class 'TestViewImplFactory' must be declared abstract or implement abstract method create(S) in 'ViewFactory'"

Java 说,以下是正确的:

@Override
public View create(Presenter presenter) {
return new TestViewImpl(presenter);
}

考虑到用户想知道将返回哪个 View 以及需要哪个 Presenter,这根本行不通。我本来期望的:

  1. 两个自动生成的文件都有错误
  2. 或两者都正确

因为它们都非常相似。我希望第一个是真的。

我在这里错过了什么?


如果我像这样将 Generic 类型添加到 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接口(interface)改成如下:

public interface ViewFactory<T extends View, S extends Presenter<T>> {

T create(S presenter);

}

所以类定义与上面问题中的方法具有相同的Generic类型。

编译后(这次使用泛型类型规范),输出如下所示:

public final class TestViewImplFactory implements ViewFactory<TestView, TestPresenter> {
public TestViewImplFactory() {
}

public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}

这样就可以编译运行成功了。

然而,这并没有回答最初的问题。为什么类型定义中明确声明的泛型正确,但方法声明中指定的继承错误且不可编译?

具体来说:为什么 Java 可以自动继承一个 Generic(在 PresenterFactory 内)而另一个不能(在 ViewFactory 内,在方法和类型声明处)?

最佳答案

为什么它不起作用:

public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}

此签名导致编译器推断 Screate() 的位置叫做。 S将是您分配的create()如:

FancyPresenter fp = presenterFactory.create();
SomeOtherPresenter sop = presenterFactory.create();

这意味着:

public TestPresenter create(){...}

不是以下的实现:

<S extends Presenter<T>> S create();

但是一个方法覆盖。没有实现接口(interface)方法。甚至不可能用具体的S 来提供任何实现。 .类似于:

public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}

这里泛型再次被推断为方法调用。所以一个实现必须接受 Presenter<T> 的每个子类型。 .唯一有效的实现是:

public interface ViewFactory<T extends View> {
T create(Presenter<T> presenter);
}

但返回类型取决于参数presenter .如果 presenter 这可能会起作用为您提供创建 T 实例的方法仅限。

为什么其他解决方案有效:

通过类型绑定(bind)方法的泛型意味着接口(interface)的实现提供了具体类型。因此,对于一个对象,您不需要提供多个不同的绑定(bind)。无论您在哪里调用create() PresenterFactory<TestView, TestPresenter<TestView>>的方法|返回类型的泛型绑定(bind)到 TestPresenter<TestView> .所以PresenterFactory<...>的每个子类型都有一个可能的实现。 .

关于java - 注释处理器似乎破坏了 Java 泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52097430/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com