[英]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.