繁体   English   中英

Eclipse Generics问题 - 解决方法?

[英]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同时提供ReallyConstantFieldF 然后将读取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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM