簡體   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