【问题标题】:"Iterable<Element> cannot be cast to List<Element>" - Isn't `List` a type of `Iterable`?“Iterable<Element> 不能转换为 List<Element>” - `List` 不是 `Iterable` 的一种吗?
【发布时间】:2011-04-26 23:17:37
【问题描述】:

我调用了一个getElements 方法,它返回Iterable&lt;Element&gt;

我这样做了:

List<Element> elements = (List<Element>) getElements();

这会产生错误:

java.lang.ClassCastException: com.utesy.Element$3 
cannot be cast to java.util.List

我认为ListIterable 的一种类型?

【问题讨论】:

  • 贴出getElements();方法的代码
  • List 接口扩展了Iterable 接口 - 所以是的,ListIterable 类型,正如你所说。但这并不意味着getElements 返回的任何Iterable 也是List。所有 List 都是 Iterable,但并非所有 Iterable 都是 List。

标签: java list classcastexception iterable


【解决方案1】:

并非所有Iterables 都是Lists,因此将任意Iterable 转换为List 是不安全的。

Set为例HashSetIterable,但是元素没有顺序,所以不能实现List接口,因此不是List.

【讨论】:

  • &lt;nit-pick&gt; "但是元素没有顺序,所以它不是List" - 这不是HashSet 不是List 的原因。 HashSet 不是 List,因为它没有实现 List 接口。 &lt;/nit-pick&gt;
  • @Matt Ball,真的...重新表述了一点...更好? :)
【解决方案2】:

从异常消息中可以清楚地看出 Iterable&lt;Element&gt; 不能转换为 List&lt;Element&gt;

所以你需要从getElements()返回List&lt;Element&gt;

【讨论】:

    【解决方案3】:

    是的,List&lt;T&gt; 扩展了 Iterable&lt;T&gt;,但这并不意味着您可以从 any Iterable&lt;T&gt; 转换为 List&lt;T&gt; - 只有当值 实际 em> 指的是List&lt;T&gt; 类型的实例。完全有可能实现Iterable&lt;T&gt; 而不实现List&lt;T&gt; 接口的其余部分......在这种情况下,你会发生什么?

    简而言之,让我们将Iterable&lt;T&gt; 更改为Object 并将List&lt;T&gt; 更改为StringString 扩展了Object,因此您可以尝试Object 转换为String...但只有在引用实际时才能在执行时成功转换em> 指的是String(或为空)。

    【讨论】:

      【解决方案4】:

      List 扩展了 Collection,而 Collection 又扩展了 Iterable。因此,您尝试强制转换为一个子类型,除非 getElements() 真的返回一个 List (签名不以任何方式保证),否则该子类型将不起作用。

      见:http://download.oracle.com/javase/1.5.0/docs/api/java/util/List.html

      【讨论】:

        【解决方案5】:

        ListIterable子接口,这意味着 List 几乎包含了 Iterable 所拥有的所有东西,但反之则不然。因此,并非 List 实例中的所有方法在 Iterable 中都有等价物。

        尽量避免这种类型的转换。

        我建议您快速查看Java 6 API 和有关铸造的教程

        【讨论】:

          【解决方案6】:

          List&lt;Element&gt;Iterable&lt;Element&gt; 的一种类型,但这并不意味着所有Iterable&lt;Element&gt; 对象都是List&lt;Element&gt; 对象。您可以将List&lt;Element&gt; 转换为Iterable&lt;Element&gt;,但反之则不行。

          苹果是一种水果,但这并不意味着所有水果都是苹果。你可以把苹果当作水果,但反过来不行。

          【讨论】:

            【解决方案7】:

            List 实现了 Iterable 接口,但这并不意味着 Iterable 可以被强制转换回 List。 Iterable 更为通用,可能是 Hash 或某种与 List 无关的奇异类型。 (看起来 getElements() 返回某个匿名内部类的实例,该类包含在其类中的 getElements 旁边)。

            如果 getElements 恰好包含列表,那么这将是一个有效的强制转换。由于 getElements() 返回的类型实际上不是 List,因此会产生运行时错误。

            【讨论】:

            • List 实现了Iterable,这确实意味着它可以被强制转换为它。 OP遇到的问题是相反的。这与它是实现还是扩展无关。
            • 对不起,“不代表可以投”不清楚,我填了“it”,以免误会你的意思。
            【解决方案8】:

            你可以把Iterable变成一个列表

            List<Element> elements = Lists.newArrayList( getElements() );
            

            【讨论】:

            • 这是最简洁的方法。否则你需要一个很长的实现:-( -- 或者只使用 Scala ;)
            【解决方案9】:

            为什么不:

                Iterable<Element> i = ...; //is what you have
                List<Element> myList = new LinkedList<Element>();
                for (Element e:i) {
                    myList.add(e);
                }
            

            ? 不需要谷歌库。

            【讨论】:

              【解决方案10】:

              你可以尝试用instanceof设置守卫:

              if (AnElement instanceof AList){
                  //cast
                  AList = (AnList)Element
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-05-06
                • 2021-12-31
                • 2016-04-14
                • 2020-06-17
                • 1970-01-01
                • 2016-09-19
                相关资源
                最近更新 更多