一般而言,convert
方法不可能工作(對於List
或任何其他類型)。
調用Field.setAccessible(true)
允許讀取和寫入私人字段,但不允許通過Field.set()
(引發IllegalAccessException: Field is final
異常)修改final
字段。
根據List
的實施情況,您嘗試複製此操作可能會妨礙其正常工作。例如,使用ArrayList
如:
// Note that this is an unchecked cast
List<ClassB> listB = (List<ClassB>) convert(listA, ArrayList.class);
試圖複製serialVersionUID
時失敗。
以下變化張貼代碼獲取圓這個問題static final serialVersionUID
在ArrayList
:
public static <A, B> B convert(A instance,
Class<B> targetClass) throws Exception {
B target = (B)targetClass.newInstance();
for (Field targetField : targetClass.getDeclaredFields()) {
targetField.setAccessible(true);
Field field =
instance.getClass().getDeclaredField(targetField.getName());
field.setAccessible(true);
// Ignore attempts to set final fields
try {
targetField.set(target, field.get(instance));
} catch (IllegalAccessException e) {
continue;
}
}
return target;
}
然而,接下來的問題是,convert
方法進行淺拷貝。對於不同類型的List
s,此更改後的版本convert
看起來可能正常工作,但它不會將列表中的ClassA
對象轉換爲ClassB
(未經檢查的轉換會隱藏此對象)。這可能會導致稍後在應用程序中拋出ClassCastException
。
解決這個問題可以通過添加另一種方法來實現包裝convert
:
public static <A, B extends List<C>, C> B convertList(
List<A> list, Class<B> targetListClass, Class<C> targetClass)
throws Exception {
B targetList = targetListClass.newInstance();
for (A object : list) {
targetList.add(convert(object, targetClass));
}
return targetList;
}
這一操作將需要被稱爲:
List<ClassB> listB = (List<ClassB>) convertList(
listA, ArrayList.class, ClassB.class);
不要這樣做。你在這裏做什麼是非常奇怪的。如果這兩種類型具有共同的操作,使它們實現一個通用的接口。 – 2010-01-08 22:25:53