“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<Element>
。
我这样做了:
List<Element> elements = (List<Element>) getElements();
这会产生错误:
java.lang.ClassCastException: com.utesy.Element$3
cannot be cast to java.util.List
我认为List
是Iterable
的一种类型?
【问题讨论】:
贴出getElements();
方法的代码
List
接口扩展了Iterable
接口 - 所以是的,List
是 Iterable
类型,正如你所说。但这并不意味着getElements
返回的任何Iterable
也是List
。所有 List 都是 Iterable,但并非所有 Iterable 都是 List。
【参考方案1】:
并非所有Iterable
s 都是List
s,因此将任意Iterable
转换为List
是不安全的。
以Set
为例,HashSet
是Iterable
,但是元素没有顺序,所以不能实现List
接口,因此不是List
.
【讨论】:
<nit-pick>
"但是元素没有顺序,所以它不是List
" - 这不是HashSet
不是List
的原因。 HashSet
不是 List
,因为它没有实现 List
接口。 </nit-pick>
@Matt Ball,真的...重新表述了一点...更好? :)【参考方案2】:
从异常消息中可以清楚地看出
Iterable<Element>
不能转换为 List<Element>
所以你需要从getElements()
返回List<Element>
【讨论】:
【参考方案3】:是的,List<T>
扩展了 Iterable<T>
,但这并不意味着您可以从 any Iterable<T>
转换为 List<T>
- 只有当值 实际 em> 指的是List<T>
类型的实例。完全有可能实现Iterable<T>
而不实现List<T>
接口的其余部分......在这种情况下,你会发生什么?
简而言之,让我们将Iterable<T>
更改为Object
并将List<T>
更改为String
。 String
扩展了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】:List
是Iterable
的子接口,这意味着 List 几乎包含了 Iterable 所拥有的所有东西,但反之则不然。因此,并非 List 实例中的所有方法在 Iterable 中都有等价物。
尽量避免这种类型的转换。
我建议您快速查看Java 6 API 和有关铸造的教程
【讨论】:
【参考方案6】:List<Element>
是Iterable<Element>
的一种类型,但这并不意味着所有Iterable<Element>
对象都是List<Element>
对象。您可以将List<Element>
转换为Iterable<Element>
,但反之则不行。
苹果是一种水果,但这并不意味着所有水果都是苹果。你可以把苹果当作水果,但反过来不行。
【讨论】:
【参考方案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` 的一种吗?的主要内容,如果未能解决你的问题,请参考以下文章