2014-01-26 32 views
1

用下面的Java代碼,有沒有辦法在第二級?:結合深泛型集合

public class Tester { 

    interface Base{}; 
    class A implements Base{} 
    class B implements Base{} 

    @Test 
    public void test(){ 
     Map<String, List<A>> a = new HashMap<String, List<A>>(); 
     Map<String, List<B>> b = new HashMap<String, List<B>>(); 

     Map<String, Base> bases = combine(a, b); 
    } 

    private Map<String, List<Base>> combine(Map<String, List<? extends Base>> one, Map<String, List<? extends Base>> two) { 
     Map<String, List<Base>> bases = new HashMap<String, List<Base>>(); 

     bases.putAll(one); 
     bases.putAll(two); 

     return bases; 
    } 
} 

的問題是,聯合收割機()方法將不匹配Map<String, List<A>>與相關泛型參數集組合到Map<String, List<? extends Base>>即使延伸基地和bases.putAll()不會接受類型的Map<String, List<? extends Base>>

回答

3

第一個問題,在combine(),你bases被聲明爲

Map<String, List<Base>> 

而是試圖把一個

Map<String, List<? extends Base>> 

List<? extends Base>不是List<Base>一個亞型,就像List<A>List<Base>的子類型。

爲了解決這個問題,改變你的basescombine是類型

Map<String, List<? extends Base>> bases = new HashMap<String, List<? extends Base>>(); 

的現在putAll方法接受一個擴展List<? extends Base>任何類型。 List<? extends Base>List<? extends Base>的子類型。

當你解決這個問題時,你有另一個問題,你的combine方法返回類型。它現在必須是

Map<String, List<? extends Base>> 

以便它可以匹配bases聲明。

這產生了第三個問題。對於Map<String, List<? extends Base>>類型的參數,Map<String, List<A>>不是有效的參數。您可以更改參數輸入

Map<String, ? extends List<? extends Base>> 

現在Map<String, List<A>>可以作爲參數傳遞。

因此,最後,它可能看起來像

@Test 
public void test() { 
    Map<String, List<A>> a = new HashMap<String, List<A>>(); 
    Map<String, List<B>> b = new HashMap<String, List<B>>(); 
    Map<String, List<? extends Base>> bases = combine(a, b); 
} 

private Map<String, List<? extends Base>> combine(
     Map<String, ? extends List<? extends Base>> one, 
     Map<String, ? extends List<? extends Base>> two) { 
    Map<String, List<? extends Base>> bases = new HashMap<String, List<? extends Base>>(); 

    bases.putAll(one); 
    bases.putAll(two); 
    return bases; 
} 

不過說實話,你真的需要那麼多級別的?儘量讓你的生活更輕鬆,如果可能的話,使用類似Bohemian的建議。

1

這裏的問題是,隨着仿製藥,List<Subclass>List<Superclass>一個實例。

要使您的代碼正常工作,請將源地圖值的類型更改爲List<Base> - 仍然可以將AB的實例添加到List<Base>

public void test() { 
    Map<String, List<Base>> a = new HashMap<String, List<Base>>(); 
    Map<String, List<Base>> b = new HashMap<String, List<Base>>(); 

    Map<String, List<Base>> bases = combine(a, b); 
} 

private Map<String, List<Base>> combine(Map<String, List<Base>> one, Map<String, List<Base>> two) { 
    Map<String, List<Base>> bases = new HashMap<String, List<Base>>(); 
    bases.putAll(one); 
    bases.putAll(two); 

    return bases; 
} 
0

考慮你允許這樣做的結合(..)

one.put("xxx", new ArrayList<B>()); 

這是有效的,因爲該聲明是Map<String, List<? extends Base>>什麼。如果你被允許通過它Map<String, List<A>>你會混合類型。

如果您將參數更改爲Map<String, ? extends List<? extends Base>>那麼我上面的示例不是有效的代碼行,您將被允許通過Map<String, List<A>>合併(..)。