![](/img/trans.png)
[英]Workaround to “allowThrowsTagsForSubclasses” issue in Eclipse Checkstyle Plug-in
[英]Eclipse Generics Issue - Workaround?
给定以下类型签名,我能够使用JDK 6和JDK 7在Maven下编译和运行代码,但是Eclipse给出了“绑定不匹配:类型F不是有界参数的有效替代<F extends Field<TP,F>>
类型的Field<TP,F>
错误在TupleVisitor。
我相信我需要这些类型,虽然我知道这很难激励给出精简的例子。 任何人都可以建议一个让我继续在Eclipse中工作的解决方法吗?
public abstract class Tuple<F extends Field<TP, F>, TP extends Tuple<F, TP>>
public class VariableTuple<F extends Field<VariableTuple<F>, F>> extends Tuple<F, VariableTuple<F>>
public class ConstantTuple<F extends Field<ConstantTuple<F>, F>> extends Tuple<F, ConstantTuple<F>>
public class Field<TP extends Tuple<F, TP>, F extends Field<TP, F>>
public class ConstantField extends Field<ConstantTuple<ConstantField>, ConstantField>
public class VariableField extends Field<VariableTuple<VariableField>, VariableField>
public interface TupleVisitor {
public <F extends Field<VariableTuple<F>, F>> void visit(VariableTuple<F> tuple, F field); //Eclipse error
public <F extends Field<ConstantTuple<F>, F>> void visit(ConstantTuple<F> tuple, F field); //Eclipse error
}
提交的错误: https : //bugs.eclipse.org/bugs/show_bug.cgi? id = 422503
没有确定简单的解决方法。 虽然Rohit Jain的回答不适用于访问者模式,但我接受了他的后续建议并将F作为类型参数从Field中移除。
这似乎是eclipse的一个错误,因为它在javac下编译也很好。 事实上,我发现与eclipse相关的自引用Java泛型相关的bug很少,但这并不存在。 所以,可能你应该提交一个。
至于解决方法,我刚刚找到一个,我怀疑你想要,因为你必须使你的界面通用。 是的,你听到了。 使用接口本身声明类型参数,使代码编译正常。 这是编译代码:
interface TupleVisitor<E extends Field<VariableTuple<E>, E>,
F extends Field<ConstantTuple<F>, F>> {
void visit(VariableTuple<E> tuple, E field);
void visit(ConstantTuple<F> tuple, F field);
}
当然有两种类型变量,因为它们的界限是不同的。 检查这是否适合你的需要,因为这听起来像是奇怪的解决方法,因为类型参数的数量取决于Tuple
类的实现者总数(实际上很奇怪,不是吗?)。 否则你必须做一些其他的改变。
问题可能是调用者提供了类型参数。 鉴于你的声明,有人可以声明
class ReallyConstantField extends ConstantField {}
然后调用TupleVisitor.visit
同时提供ReallyConstantField
为F
。 然后将读取visit
方法的类型约束
ReallyConstantField extends Field<ConstantTuple<ReallyConstantField>, ReallyConstantField>
所以我们使用ConstantTuple<ReallyConstantField>
。 然后将读取该类的类型约束
ReallyConstantField extends Field<ConstantTuple<ReallyConstantField>, ReallyConstantField>
这是不正确的,因为ReallyConstantField
是一个ConstantField
,它是一个Field<ConstantTuple<ConstantField>, ConstantField>
,这是一个不可转换的类型。
也就是说,即使您使用extends
边界声明类型参数,唯一有效的类型参数也是单一类型。 也就是说,您根本不需要类型参数,但可以简单地声明:
void visit(ConstantTuple<ConstantField> tuple, ConstantField field);
更新
顺便说一句,如果这些应该是,如示例所示,并行类层次结构与不同层次结构的类之间具有一对一的对应关系,则有一种更简单的方式来编写泛型:
abstract class Tuple<F extends Field<TP, F>, TP extends Tuple<F, TP>> {}
class VariableTuple extends Tuple<VariableField, VariableTuple> {}
class ConstantTuple extends Tuple<ConstantField, ConstantTuple> {}
class Field<TP extends Tuple<F, TP>, F extends Field<TP, F>> {}
class ConstantField extends Field<ConstantTuple, ConstantField> {}
class VariableField extends Field<VariableTuple, VariableField> {}
interface TupleVisitor {
public void visit(VariableTuple tuple, VariableField field);
public void visit(ConstantTuple tuple, ConstantField field);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.