我从以下代码段收到编译器错误。错误发生在指示的行:
static abstract class AbstractRoot<R extends Root<R>> implements Root<R> {
private final Map<Grouping, Phrase> m_ph;
AbstractSqlRoot() { this.m_ph = new HashMap<>(); }
@Override public PhraseBuilder<R> phrase() {
PhraseBuilder<R> fr = (PhraseBuilder<R>) m_ph.get(Grouping.PHRASE);
if (fr == null) {
--> fr = new PhraseBuilder<R>(this);
m_ph.put(Grouping.PHRASE, fr);
}
return fr;
}
HashMap m_ph
是一种类型安全的异类容器。类型链接由Grouping
枚举类提供,因此代码中存在的强制转换是安全的。
PhraseBuilder的类定义(及其自己的AbstractPhraseBuilder)如下所示:
public static abstract class AbstractPhrase<R extends Root<R>> implements Phrase {
private final List<Element> m_elem;
private final R m_root;
AbstractPhrase(R r)
{ m_elem = new ArrayList<>(); m_root = r; }
:
:
}
public static final class PhraseBuilder<R extends Root<R>> extends AbstractPhrase<R> {
public PhraseBuilder() { this(null); }
public PhraseBuilder(R r) { super(r); }
:
:
}
编译器报告&#34;不兼容的类型:AbstractRoot<R>
无法转换为R,其中R是类型变量:R extends Root<R>
中声明的AbstractRoot
。&#34;
我很困惑。 AbstractRoot
被声明为实现Root<R>
,因此它应该与为&#34; extends Root<R>
&#34;定义的参数兼容。我没有看到指示的构造函数调用和类定义之间存在冲突。
任何人都能帮助我解决这个难题吗?我被卡住了。
更新:感谢下面给出的答案,我得到了我错的地方。 SqlRoot<R>
接口的设计确实需要将R
发送到PhraseBuilder
类。代码已修补如下以解决此问题:
static abstract class AbstractRoot<R extends Root<R>> implements Root<R> {
private final Map<Grouping, Phrase> m_ph;
AbstractSqlRoot() { this.m_ph = new HashMap<>(); }
@Override public PhraseBuilder<R> phrase() {
PhraseBuilder<R> fr = (PhraseBuilder<R>) m_ph.get(Grouping.PHRASE);
if (fr == null) {
--> fr = new PhraseBuilder<R>(typedThis());
m_ph.put(Grouping.PHRASE, fr);
}
return fr;
}
:
:
protected abstract R typedThis();
}
子类ConcreteRoot
的类定义现在包含typedThis()
的方法声明。不是理想的解决方案,因为该方法成为了类导出的API的一部分,但它解决了这个问题:
static final class ConcreteRoot extends AbstractRoot<ConcreteRoot> {
ConcreteRoot() { super(); }
@Override protected ConcreteRoot typedThis() { return this; }
:
:
}
答案 0 :(得分:4)
new PhraseBuilder<R>(this)
正在尝试调用此构造函数:
public PhraseBuilder(R r) { super(r); }
问题是this
不是R
:它是AbstractRoot<R>
,它恰好是Root<R>
,但它是R
。根本不是fr = new PhraseBuilder<Root<R>>(this);
。也许你的意思是这个?
{{1}}
答案 1 :(得分:2)
问题是this
是Root<R>
,不一定是R
。声音混乱?它是。这是一个反作用的反例:
public class MyRootA extends AbstractRoot<MyRootA> {
//R is MyRootA - "this" is an instance of R
}
public class MyRootB extends AbstractRoot<MyRootA> {
//R is MyRootA - "this" is NOT an instance of R
}
换句话说,没有任何内容表明R
与this
的类型相同。
这样的自我打字通常会适得其反。通常只需使用更通用的类型Root<R>
即可。如果你真的想要这个,一个技巧就是间接获得对this
的引用:
fr = new PhraseBuilder<R>(this.typedThis());
你在Root<R>
声明的地方:
R typedThis();
并且具体类的实现通常只是:
public MyRootA typedThis() {
return this;
}