2011-08-08 77 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. 
} 
相关问题