假设有一个方法返回 Object
,但我们知道它是某种类型的 List
(例如 LinkedList<Long>
或 ArrayList<String>
):
public abstract Object open();
直接使用其返回值
List<Long> result = (List<Long>)dialog.open();
将导致警告,例如:
类型安全:从对象到列表的未经检查的转换
<小时/>为了解决这个问题,我们可以转换为 List<?>
然后分别检查每个列表项:
List<?> result = (List<?>)dialog.open();
List<Long> safeResult = new LinkedList<Long>();
for (Object obj: result) {
if (obj instanceof Long) {
safeResult.add((Long)obj);
}
}
<小时/>
现在我想,如果有一个可以转换 Object
的泛型方法不是很好吗? (已知包含 List
)到 List
的任何类型化实例.
这是我能得到的最接近的结果:
private <T> List<T> doSafeCast(Object listObject, Class<T> type) {
List<T> result = new LinkedList<T>();
if (listObject instanceof List) {
List<?> list = (List<?>)listObject;
for (Object obj: list) {
if (type.isInstance(obj)) {
result.add(type.cast(obj));
}
}
}
return result;
}
现在我可以像这样使用它:
List<Long> safeResult = this.doSafeCast(dialog.open(), Long.class);
但是,现在我一定有LinkedList
仅作为结果。
是否也可以通过传递附加参数来指定列表类型?
我想要这样的事情:
List<Long> safeResult = this.doSafeCast(dialog.open(), Long.class, ArrayList.class);
List<String> anotherSafeResult = this.doSafeCast(anotherDialog.open(), String.class, LinkedList.class);
我知道这一切看起来过于复杂,我可以添加 @SuppressWarnings("unchecked")
如果我确定对话框将始终返回所需的类型,那么我最初的不安全转换。但我想出了一个想法,即有一个通用方法来进行此类安全转换,现在我想知道这是否可能。所以请不要建议其他解决方案,我只是想在这里更多地了解如何使用泛型。 :-) 谢谢。
最佳答案
是的,可以。只需为该方法引入另一个类型参数并将其向上绑定(bind)到 List
:
private <T, L extends List<T>> List<T> doSafeCast(Object listObject,
Class<T> type,
Class<L> listClass) {
List<T> result = listClass.newInstance();
if (listObject instanceof List) {
List<?> list = (List<?>) listObject;
for (Object obj : list) {
if (type.isInstance(obj)) {
result.add(type.cast(obj));
}
}
}
return result;
}
请注意,您必须处理一些可能的异常。
关于java - 从 Object 转换为 List 的类型化实例的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28766478/