【问题标题】:Why can't Java convert an ArrayList<TreeSet<Integer>> into a List<Set<Object>>?为什么 Java 不能将 ArrayList<TreeSet<Integer>> 转换为 List<Set<Object>>?
【发布时间】:2011-08-08 16:21:33
【问题描述】:

我正在尝试做一些看起来相当简单的事情:对集合列表的大小求和。 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呢?

【问题讨论】:

  • 正确的问题标题应该是“为什么 Java 不能将 ArrayList&lt;TreeSet&lt;Integer&gt;&gt; 转换为 List&lt;Set&lt;Object&gt;&gt;?”

标签: java generics


【解决方案1】:

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

【讨论】:

  • 但是,List&lt;Integer&gt;List&lt;? extends Object&gt;
  • 使用Set&lt;? extends Object&gt; 导致actual argument java.util.ArrayList&lt;java.util.TreeSet&lt;java.lang.Integer&gt;&gt; cannot be converted to java.util.List&lt;java.util.Set&lt;? extends java.lang.Object&gt;&gt;
  • 使用List&lt;? extends Set&lt;? extends Object&gt;&gt; :)
  • @Petar:您在 cmets 中提供的解决方案有效,但解释(为什么 Java 不允许这样做)不正确。用List&lt;Set&lt;String&gt;&gt; 调用sizeOfListOfSets(List&lt;Set&lt;Object&gt;&gt;) 不会导致任何概念问题。只有当方法修改参数对象时才会出现问题。
  • @Chris:使用List&lt;Set&lt;String&gt;&gt; 调用sizeOfListOfSets(List&lt;Set&lt;Object&gt;&gt;) 将导致编译时错误。
【解决方案2】:

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

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

这是因为例如,如果您有一个声明为 List&lt;Object&gt; 的参数,并且您可以将其传递给 List&lt;Integer&gt;,那么您将能够向该列表添加任何类型的对象,这会破坏类型安全.

虽然有一个使用通配符? 的解决方法,但您仍然无法添加元素,除非您像&lt;? super MyObject&gt; 那样执行此操作,因为继承树上更高的任何内容都可以添加到列表中。

【讨论】:

    【解决方案3】:

    问题不是从整数转换为对象,而是从整数列表转换为对象列表失败,因为List&lt;Integer&gt; 不是List&lt;Object&gt;。 Java 编译器不会尝试自动转换泛型类型。

    您可以将您的方法声明更改为类似这样的内容来避免错误:

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

    【讨论】:

    • 更多信息请见this
    • 这仍然导致错误,但是public static int sizeOfListOfSets(List&lt;? extends Set&lt;?&gt;&gt; list) 没有。感谢您的回复。
    • @houman001 - 一定是List&lt;? extends Set&lt;? extends Object&gt;&gt; :)
    【解决方案4】:

    因为这将使您能够将任何对象放入该列表中。当您稍后从原始列表引用访问元素时,它将包含非整数对象,尽管列表仍被声明为 List&lt;Integer&gt; - 这意味着您不能再依赖类型所说的内容。示例:

    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.
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-08
      • 2019-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多