2011-08-08 76 views
5

我正在嘗試做一些看起來相當簡單的事情:總結一組列表的大小。 Netbeans中給出瞭如下警告/錯誤:爲什麼Java不能將ArrayList <TreeSet <Integer>>轉換爲列表<Set<Object>>?

actual argument java.util.ArrayList<java.util.TreeSet<java.lang.Integer>> cannot be converted to java.util.List<java.util.Set<java.lang.Object>> by method invocation conversion 

以下兩件代碼:

ArrayList<TreeSet<Integer>> testList = new ArrayList<TreeSet<Integer>>(); 
    TreeSet<Integer>   testSet; 
    int       size = 0; 

    testSet = new TreeSet<Integer>(); 
    testSet.add(new Integer(++size)); 
    testSet.add(new Integer(++size)); 
    testList.add(testSet); 
    testSet = new TreeSet<Integer>(); 
    testSet.add(new Integer(++size)); 
    testList.add(testSet); 

    int expResult = size; 
    int result = Helpers.sizeOfListOfSets(testList); 

最後一行給出了:

/** 
* Sums the sizes of all sets in a list. Note that while there will be 
* no duplicate elements in a single set, "sister" sets may contain 
* elements, so the value returned is **not** equal to the number of unique 
* elements in all sets. 
* @param list, a List of Sets 
* @return the number of elements contained in all sets 
*/ 
public static int sizeOfListOfSets(List<Set<Object>> list) { 
    int size = 0; 

    for (Set<Object> set : list) { 
     size += set.size(); 
    } 

    return size; 
} 

,然後用下面的調用它編譯錯誤:

error: method sizeOfListOfSets in class Helpers cannot be applied to given types; 
1 error 

那麼,爲什麼不能將java.lang.Integer轉換爲java.lang.Object?

+1

正確的問題的標題是, 「爲什麼不能轉換成Java的一個'的ArrayList >'入'名單>'?」 –

回答

14

A List<Integer>不是List<Object>。如果Java允許,那麼你可以調用List<String>的方法,你會被打破。由於Jeremy Heiler指出,你可以使用List<? extends Object>,你會沒事的。這意味着允許延伸Object的每種類型。用通用術語將?稱爲wildcard

+1

但是,'List '是一個'List <?擴展Object>'。 – Jeremy

+0

@Jeremy Heiler - 是的。 –

+0

使用'Set <? extends Object>'lead to'實際參數java.util.ArrayList >不能轉換爲java.util.List >' – MrDrews

2

任何你聲明爲通用類型的東西必須是完全相同通用類型總是。是可以改變的唯一想到的是基本類型,即:

List<MyObject> myList = new ArrayList<MyObject>; 

這是因爲,例如,如果你有一個參數聲明爲List<Object>,你可以通過它一個List<Integer>,那麼你就可以添加任何類型的對象,這將打破類型安全。

雖然使用通配符?一種解決方法,你仍然不能,除非你做這樣的<? super MyObject>添加元素,因爲任何在繼承樹高將是確定添加到列表中。

2

該問題不是從Integer轉換爲Object,而是從Integer列表轉換爲Object失敗的列表,因爲List<Integer>不是List<Object>。 Java編譯器不會嘗試自動轉換泛型類型。

你可能你的方法聲明中改變這樣的事情來擺脫錯誤:

public static int sizeOfListOfSets(List<Set<? extends Object>> list) 
+0

有關更多信息,請參見[this](http://download.oracle.com/javase/tutorial/java/generics/subtyping.html)。 – n0rm1e

+0

這仍然導致錯誤,但是'public static int sizeOfListOfSets(List <?extends Set > list)'沒有。謝謝回覆。 – MrDrews

+0

@ houman001 - 它必須是'List <?擴展Set <?擴展對象>>':) –

0

因爲這能讓你把任何物體在該列表中。當您從原始列表引用中稍後訪問元素時,它將包含非Integer對象,儘管該列表仍被聲明爲List<Integer>--這意味着您不能再依賴於該類型。例如:

List<Integer> intList = new ArrayList<Integer>(); 
doSomething(intList); 
for (Integer i : intList) { 
    // i must be an Integer, so doSomething must not 
    // be able to put non-Integers into that list. 
} 
相關問題