簡體   English   中英

我可以簡化此Java Generics層次結構嗎?

[英]Can I simplify this Java Generics Hierarchy

有時在我的代碼中,我想引用(我認為的)泛型層次結構中的隱式類型(基本上是第一個隱含的類型?在下面)。

public class Foo<BAR extends Bar<?>> {
  public void t(BAR x) {
    List l = new ArrayList();
    Object baz = x.makeBaz(null);
    l.add(baz);
    x.setBazList(l);
  }
}

public interface Bar<BAZ extends Number> {
  public BAZ makeBaz(Object arg1);
  public List<BAZ> getBazList();
  public void setBazList(List<BAZ> baz);
}

例如,在上面的代碼中可以替換行

    List l = new ArrayList();
    Object baz = x.makeBaz(null);

用泛型的東西?

我寧願避免寫:

public class Foo<BAZ extends Number, BAR extends Bar<BAZ>> {
  public void t(BAR x) {
    List<BAZ> l = new ArrayList<BAZ>();
    BAZ baz = x.makeBaz(null);
    l.add(baz);
  }
}

因為強制執行任何派生類的聲明會感覺不自然。

我知道上面的內容有點人為,但它比試圖顯示我正在查看的實際代碼要簡單得多。

我想主要的問題是你需要以某種方式強制你從x.makeBaz()獲得的類型與你給x.setBazList(l)的列表的類型參數相同,如果你只是使用? 你失去了執法能力,所以你需要一個通用的類型參數。 但從某種意義上說,類型參數只需要在那幾行中“本地”,並且類的其余部分不需要知道。

您可以使用類型參數BAZ來僅參數化方法而不是類:

public <BAZ extends Number> void t2(Bar<BAZ> x) {
  List<BAZ> l = new ArrayList<BAZ>();
  BAZ baz = x.makeBaz(null);
  l.add(baz);
  x.setBazList(l);
}

這用於本地化我們需要這個臨時類型變量BAZ的代碼區域。 請注意,此方法的簽名實際上是public void t2(Bar<?> x) ,即外部不需要知道此BAZ

現在,這個方法現在接受所有Bar<anything>而不是BAR 如果這是一個問題,你可以“包裝”上面的方法。 我們沒有和以前一樣的問題,因為所有的BAZ內容都已經包含在t2() ,這需要一個Bar<anything> ,所以我們可以安全地傳遞一個BAR

public void t(BAR x) {
  t2(x);
}

我同意這似乎有點迂回。 也許其他人會想出更好的方法。

當BAZ擴展Number時,您至少可以綁定到Number

public class Foo<BAR extends Bar<?>> {
    public void t(BAR x) {    
        List<Number> l = new ArrayList<Number>();
        Number baz = x.makeBaz(null);
        l.add(baz);
        // l.add(Integer.valueOf(1)); compiles but with this here the next line throws ClassCastException
        x.setBazList(l);
    }
}

public interface Bar<BAZ extends Number> {
    public BAZ makeBaz(Object arg1);
    public List<BAZ> getBazList();
    public void setBazList(List<BAZ> baz);
}

public class BarConcreate implements Bar<BigDecimal>{
    long counter = 1;

    private List<BigDecimal> list = new ArrayList<BigDecimal>();
    public List<BigDecimal> getBazList() {
        return list;
    }


    public BigDecimal makeBaz(Object arg1) {
        return BigDecimal.valueOf(counter++);
    }

    public void setBazList(List<BigDecimal> baz) {
        list = baz;         
        for(BigDecimal d : baz){
            logger.debug("value:" + d.toString());
        }
    }

}


public void TestFooBar(){
    Foo<Bar<BigDecimal>> foo = new Foo<Bar<BigDecimal>>();
    Bar<BigDecimal> bar = new BarConcreate();
    foo.t(bar);
}

這個java編譯並運行,如果List只用BigDecimal填充,如果List中有一個整數,每個東西都可以工作,我們在x.setBazList(l)行上得到一個類轉換異常;

我覺得很有意思。

如果你願意,我會選擇這個:

List<Number> l = new ArrayList<Number>();
Number baz = x.makeBaz(null);

希望這可以幫助。

編輯:這也是有道理的:

public class Foo<BAR extends Bar<? extends Number>>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM