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