“Iterable<Element> 不能转换为 List<Element>” - `List` 不是 `Iterable` 的一种吗?

Posted

技术标签:

【中文标题】“Iterable<Element> 不能转换为 List<Element>” - `List` 不是 `Iterable` 的一种吗?【英文标题】:"Iterable<Element> cannot be cast to List<Element>" - Isn't `List` a type of `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。 【参考方案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

【讨论】:

以上是关于“Iterable<Element> 不能转换为 List<Element>” - `List` 不是 `Iterable` 的一种吗?的主要内容,如果未能解决你的问题,请参考以下文章