在Java 1.5中将非genericsList类型转换为Generic List类型
我有一个List,保证只包含一个类型对象。 这是由我无法更新的库中的某些底层代码创建的。 我想基于传入的List对象创建一个List ,以便我的调用代码与List 进行通信。
将List(或任何其他对象集合)转换为List 的最佳方法是什么。
在与未指定generics类型的类型参数的遗留代码进行交互操作时,请使用通配符。 例如,假设您在旧库中调用一个只返回原始Collection
:
Collection getItems();
在您的代码中,将结果分配给使用通配符声明的变量:
Collection> items = widget.getItems();
这样,您可以保留类型安全性,这样您就不会收到任何警告。
遗留代码可能指定(在评论中,最有可能)通用参数应该是什么。 例如:
/** * @return the items, as a Collection of {@link Item} instances. */ Collection getItems();
在这种情况下,您可以选择。 您可以将结果转换为Collection
,但是如果这样做,您将100%依赖第三方库,并放弃Javagenerics类型的保证:在运行时引发的任何ClassCastException
都将发生在显性演员。
如果您不完全信任第三方库,但仍需要生成Collection
怎么办? 然后创建一个新集合,并在将它们转换为期望的类型后添加内容。 这样一来,如果库中有一个bug,你就会马上发现它,而不是让一些代码远离它,然后很快就会出现ClassCastException
。
例如:
Collection> tmp = widget.getItems(); Collection- items = new ArrayList
- (tmp.size()); for (Object o : tmp) items.add((Item) o); /* Any type error will be discovered here! */
对于在编译时未知类型参数的情况,可以使用Collections
类的类型检查的集合工厂 。
您可以简单地转换列表:
List raw = new ArrayList(); List generic = (List ) raw;
最好和最安全的方法是使用java.util.Collections方法’checkedList(列表列表,类类型)’
使用此方法,将尽早检查旧列表中的所有项目。
尝试这个:
List objectsWithType = Arrays.asList((ObjectType[])wildcardObjects).toArray());
但请记住,这将产生一个固定长度的List。 如果您尝试在此列表中添加或删除元素,则会引发错误。 所以在使用Arrays.asList()
要小心。
如果您只是在任何旧位置转换为List
,您将收到“未经检查”的编译器警告。 我们通过将其移动到实用方法来解决这个问题。
public class Lists { @SuppressWarnings({"unchecked"}) public static List cast(List> list) { return (List ) list; } }
来电者现在没有警告,例如:
for (Element child : Lists.cast(parent.getChildren())) { // ... }
那个checkedList
实用程序在理论上是一个好主意,但实际上很难传入你期望的类。 我希望Java最终能获得运行时通用的输入信息。