2016-11-20 79 views
0

我在嘗試泛型上/下界的一些示例程序。泛型上界給出了編譯錯誤...但下限是好的。 我只是想把類型T的列表放入一個集合,並嘗試上下限場景。泛型上界通配符給出編譯錯誤

請幫助確定與testUpperBound(T t)方法的問題以及爲什麼testLowerBound(T t)方法編譯並且testUpperBound(T t)沒有。我檢查了其他類似的線程..但我仍然沒有清楚。

請讓我知道是否需要更多的細節。

public class TestGenerics<T> 
    { 

     public static void main(String...args) 
     { 
      List<String> list = new ArrayList<>(); 
      list.add("New ArrayList"); 
      new TestGenerics<List<String>>().testUpperBound(list); 
      new TestGenerics<List<String>>().testLowerBound(list); 

     } 

     public void testLowerBound(T t) 
     { 
      Set<? super ArrayList<T>> lowerBoundSet = new HashSet<>(); 
      lowerBoundSet = new HashSet<List<T>>(); 
      ArrayList<T> list = new ArrayList<>(); 
      list.add(t); 
      lowerBoundSet.add(list); // compiles.. 

      out.println(lowerBoundSet); 
     } 

     public void testUpperBound(T t) 
     { 
      Set<? extends List<T>> upperBoundSet = new HashSet<>(); 
      upperBoundSet = new HashSet<List<T>>(); 
      ArrayList<T> list = new ArrayList<>(); 
      list.add(t); 
      upperBoundSet.add(list); // Doesn't compile.. 

      out.println(upperBoundSet); 
     } 

    } 

回答

0

這裏沒有這樣的限制,你有你的答案:

Explanation of the get-put principle

它是Java規則,這就是全部。 我可以給你和你的代碼的例子,爲什麼,如果編譯通過這將是不安全的:

public void extendsExample(){ 
    Set<? extends List<? extends String>> setOfList = new HashSet<>(); 
    Set<ArrayList<String>> setOfArrayList = new HashSet<>(); 

    // now setOfList var refers to a set 
    // which contains a arraylist of String 
    setOfList = setOfArrayList; 

    // compilation fails 
    setOfList.add(new LinkedList<String>()); 
} 

想象編譯不會失敗。
這意味着setOfArrayList這個實例是一個應該包含ArrayList實例的集合,現在包含一個LinkedList元素的列表。

如果您在setOfArrayList上進行迭代,則不會像預期的那樣單獨使用ArrayList<String>元素。這是不安全的,這就是編譯失敗的原因。

下面的例子與<? super

public void superExample(){ 
    Set<? super ArrayList<String>> setOfArrayList = new HashSet<>(); 

    // compilation ok 
    setOfArrayList.add(new ArrayList<String>()); 
    // new anonymous type derivating from ArrayList 
    ArrayList<String> derivedArrayList = new ArrayList<String>(){ 
    }; 
    // compilation ok 
    setOfArrayList.add(derivedArrayList); 
} 
+0

真棒:) ..最後我明白了....感謝大衛..! 。讚賞和接受答案。 –

0

您不能修改使用<? extends SomeType>參數化的集合。 Java只是不允許,因爲它不是安全的行爲。 add()修改集合,所以你不能這樣做。沒有爲<? super SomeType>

+0

感謝您回答雅羅斯拉夫...但是,請你幫忙找到我的代碼中低級和高級方法之間的區別究竟是什麼,下級編譯和上級方法之間沒有區別? –

+0

不是,你不能插入'Collection ',但你可以插入'Collection ',反之亦然(可以從''檢索,不能從''檢索)。 Iirc仍然可以通過鑄造從''中檢索,但通常它是PECS的擴展 – Rogue

+0

至於限制背後的原因......它涉及到類型擦除。 Java在運行時並不知道確切的參數化,所以對於上限集合,修改是潛在的危險操作。如果互聯網中沒有這樣的限制,會出現很多例子。 –

0

簡單地說,我們不知道在什麼列表的類型都包含在upperBoundSet編譯時間。它可能是Set<ArrayList<T>>,或者它可能是Set<LinkedList<T>>,或者它可能是許多其他選擇之一。

如果結果是Set<LinkedList<T>>,那麼在它上面加上ArrayList顯然是一個壞主意。但是因爲我們不知道該設備的內容是什麼類型,所以需要更安全的選項並將其屏蔽。