我正在尝试为here发布的问题扩展解决方案。
共享的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&lt; Map&gt;转换列出&lt; Map&lt; String,Object&gt;&gt;。有没有办法扩展castList来做到这一点?
List<Map<String, Object>> list = castList(out.get("o_cursor"), Map.class);
我尝试了一个特定于地图列表的修改版本,但仍然出现错误&#34;方法castMapList(Object,Class&lt; Map&lt; K,V&gt;&gt;)不适用于参数 (对象,类&lt;地图&gt;)&#34;这似乎是同一错误的不同风格。
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;
}
答案 0 :(得分:2)
由于删除,有:
Class<Map<K, V>>
。Map
是否有某些特定K
和V
。那是:
Class
对象,例如Map.class
是Class<Map>
。obj instanceof Map<K, V>
这样的东西是编译器错误而Class
个对象不检查通用参数,例如isInstance
和cast
。Point-being,如果没有额外的工作,你无法在运行时验证泛型。
您仍然可以围绕它进行编程,具体取决于您正在做什么。例如,一种简单的方法就是重建每个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
。
答案 1 :(得分:0)
我不确定是否有未经检查的警告对您而言是一个问题。对于地图,您可以执行以下操作:
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
来自public sealed class ExpandoObject : IDynamicMetaObjectProvider,
IDictionary<string, object>, ICollection<KeyValuePair<string, object>>,
IEnumerable<KeyValuePair<string, object>>, IEnumerable, INotifyPropertyChanged
,他们也会这样做。您必须确保该列表包含地图。
答案 2 :(得分:0)
这就是我想出的。再次感谢!
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();
}
}