[英]Unchecked cast from Object to List
我正在尝试扩展此处发布的问题的解决方案。
在那里共享的castList方法对于非泛型类型非常有用。
public static <T> List<T> castList(Object obj, Class<T> clazz)
{
List<T> result = new ArrayList<T>();
if(obj instanceof List<?>)
{
for (Object o : (List<?>) obj)
{
result.add(clazz.cast(o));
}
return result;
}
return null;
}
当返回类型不是简单的字符串列表,而是列表本身是另一个泛型(例如地图列表)时,我们遇到的问题就是尝试使用相同的想法。
List<Map<String, Object>> list = (List<Map<String, Object>>) out.get("o_cursor");
尝试按以下方式使用castList会导致类型不匹配:无法从List <Map>转换为List <Map <String,Object >>。 有没有办法扩展castList来做到这一点?
List<Map<String, Object>> list = castList(out.get("o_cursor"), Map.class);
我尝试了特定于地图列表的修改版本,但仍然收到错误消息“方法castMapList(Object,Class <Map <K,V >>)不适用于参数(Object,Class <Map>)”像是同一错误的不同风味。
public static <K, V> List<Map<K, V>> castMapList(Object object, Class<Map<K, V>> clazz) {
if (object instanceof List<?>) {
List <Map<K, V>> result = new ArrayList<Map<K, V>>();
for (Object o: (List<?>) object) {
result.add(clazz.cast(o));
}
return result;
}
return null;
}
由于擦除,存在:
Class<Map<K, V>>
。 Map
是否具有特定的K
和V
那是:
Map.class
,每个泛型类都有一个对应的原始类型Class
对象,例如Map.class
是Class<Map>
。 obj instanceof Map<K, V>
Class
东西是编译器错误,并且Class
对象不使用isInstance
和cast
检查通用参数。 值得一提的是,如果没有一些额外的工作,您将无法在运行时验证泛型。
您仍然可以围绕它进行编程,具体取决于您在做什么。 例如,一种简单的方法就是重建每个Map
,就像重建List
:
static <K, V> List<Map<K, V>> castMapList(
Object obj, Class<K> keyType, Class<V> valueType) {
if (obj instanceof List<?>) {
List<Map<K, V>> result = new ArrayList<>();
for (Object element : (List<?>) obj) {
if (element instanceof Map<?, ?>) {
Map<K, V> map = new HashMap<>();
for (Map.Entry<?, ?> entry : (Map<?, ?>) element) {
map.put(keyType.cast(entry.getKey()),
valueType.cast(entry.getValue());
}
result.add(map);
} else {
// do something that you want?
// personally I would throw ClassCastExceptions
// but you seem to be returning null
}
}
return result;
}
return null;
}
另外,例如,看起来您似乎正在进行某种反序列化,并且可以将Class
烘烤到要序列化的Map
中:
public class MyCheckedMap<K, V>
extends SomeMapImplementation<K, V>
implements Serializable {
private static final long serialVersionUID = 1L;
private final Class<K> keyType;
private final Class<V> valueType;
public MyCheckedMap(Class<K> keyType, Class<V> valueType) {
this.keyType = Objects.requireNonNull(keyType);
this.valueType = Objects.requireNonNull(valueType);
}
@SuppressWarnings("unchecked")
public static <K, V> MyCheckedMap<K, V> cast(
Object obj, Class<K> keyType, Class<V> valueType) {
if (!(obj instanceof MyCheckedMap<?, ?>))
throw new ClassCastException(obj.getClass().toString());
MyCheckedMap<?, ?> map = (MyCheckedMap<?, ?>) obj;
validate(keyType, map.keyType);
validate(valueType, map.valueType);
return (MyCheckedMap<K, V>) obj;
}
private static void validate(Class<?> lhs, Class<?> rhs) {
if (lhs == rhs)
return;
throw new ClassCastException(String.format("%s != %s", lhs, rhs));
}
}
您必须为每个List
, Map
等编写一些样板代码,但可能只做不到。
还有其他一些方法可以解决此类问题,例如Neal Gafter的Super Type Tokens和Guava的TypeToken
,这是Neal Gafter的思想的衍生。 这些本质上使用反射来实现MyCheckedMap
类的MyCheckedMap
。
我不确定是否存在未经检查的警告对您来说是否是一个问题。 对于地图,您可以执行以下操作:
public <K, V> List<Map<K, V>> castMapList(Object object, Class<K> class1, Class<V> class2) {
if (object instanceof List<?>) {
List<Map<K, V>> result = new ArrayList<>();
for (Map<K, V> o : (List<Map<K, V>>) object) { //Unchecked cast
result.add(o);
}
return result;
}
return null;
}
要么
for (Object o : (List<?>) object) {
if (o instanceof Map<?, ?>) {
result.add((Map<K, V>) o); //Unchecked cast
}
}
我认为对您来说,不发出抑制警告是最糟糕的情况,因为即使在Class.java
的cast方法中 ,他们也会这样做。 您必须确保列表中包含地图。
这就是我想出的。 再次感谢!
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CastUtility {
public static <T> List<T> castList(Object object, Class<T> clazz) {
if (object == null) {
return null;
}
if (object instanceof List<?>) {
List<T> result = new ArrayList<T>();
for (Object o : (List<?>) object) {
result.add(clazz.cast(o));
}
return result;
}
throw new ClassCastException();
}
public static <K, V> Map<K, V> castMap(Object object, Class<K> keyType,
Class<V> valueType) {
if (object == null) {
return null;
}
if (object instanceof Map<?, ?>) {
Map<K, V> result = new HashMap<K, V>();
for (Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) {
result.put(keyType.cast(entry.getKey()),
valueType.cast(entry.getValue()));
}
return result;
}
throw new ClassCastException();
}
public static <K, V> List<Map<K, V>> castMapList(Object object,
Class<K> keyType, Class<V> valueType) {
if (object == null) {
return null;
}
if (object instanceof List<?>) {
List<Map<K, V>> result = new ArrayList<Map<K, V>>();
for (Object o : (List<?>) object) {
result.add(castMap(o, keyType, valueType));
}
return result;
}
throw new ClassCastException();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.