[英]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.