为什么Java不能转换ArrayList <treeset <integer>&gt;到List <set <object>&gt;?</set <object> </treeset <integer>

时间:2011-08-08 16:21:34

标签: java generics

我正在尝试做一些看似相当简单的事情:总结一组列表的大小。 Netbeans给出以下警告/错误:

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

以下两段代码:

/**
 * 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;
}

然后使用以下内容调用它:

    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);

最后一行给出了编译错误:

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

那么,为什么不能将java.lang.Integer转换为java.lang.Object?

4 个答案:

答案 0 :(得分:14)

List<Integer>不是List<Object>。如果Java允许,那么您可以使用List<String>调用该方法,您将被破坏。正如Jeremy Heiler指出你可以使用List<? extends Object>而你会没事的。这意味着允许扩展Object的每种类型。 ?在通用术语中称为wildcard

答案 1 :(得分:2)

您声明为通用类型的任何内容都必须始终是 完全相同的 泛型类型。可以改变的唯一想法是基本类型,即:

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

这是因为例如,如果你有一个声明为List<Object>的参数,并且你可以将它传递给List<Integer>,那么你就可以在该列表中添加任何类型的对象,打破类型安全。

虽然使用通配符?有一种解决方法,但除非你这样做<? super MyObject>,否则你仍然无法添加元素,因为继承树上任何更高的元素都可以添加列表。

答案 2 :(得分:2)

问题不是从Integer转换为Object,而是从Integer列表转换为Object列表失败,因为List<Integer>不是List<Object>。 Java编译器不会尝试自动转换泛型类型。

您可以将方法声明更改为类似的内容以消除错误:

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

答案 3 :(得分: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.
}