一般而言,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