将列表值反映到另一个列表中? [英] Reflect a list value into another list?
问题描述
List <ClassA> listA; List <ClassB> listB;
我可以使用反射将 listA 反射到 listB 中吗?我得到了下面的代码,但只反映了一个对象
Can I use reflection to reflect listA into listB? I got below code but only reflect an object
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);
targetField.set(target, field.get(instance));
}
return target;
}
推荐答案
一般来说 convert
方法不太可能工作(对于 List
s 或任何其他类型).
In general the convert
method is not likely to work (for List
s or any other type).
调用 Field.setAccessible(true)
允许对私有字段进行读写访问,但不允许通过 Field.set()<修改
final
字段/code>(抛出一个 IllegalAccessException: Field is final
异常).
Calling Field.setAccessible(true)
allows read and write access to private fields but will not allow modification of final
fields via Field.set()
(an IllegalAccessException: Field is final
exception is thrown).
根据 List
的实现,您尝试复制这可能会阻止它正常工作.例如,使用ArrayList
如:
Depending on the implementation of List
you are trying to copy this may prevent it from working correctly. For example, using ArrayList
such as:
// Note that this is an unchecked cast
List<ClassB> listB = (List<ClassB>) convert(listA, ArrayList.class);
尝试复制 serialVersionUID
时失败.
对已发布代码的以下更改解决了 ArrayList
中 static final serialVersionUID
的这个问题:
The following change to the posted code gets round this problem for static final serialVersionUID
in 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
稍后在应用程序中抛出.
However, the next problem is that the convert
method is performing a shallow copy. For List
s of different types this altered version of convert
may appear to work correctly but it does not convert the ClassA
objects in the list to ClassB
(the unchecked cast above hides this). This will likely cause ClassCastException
s to be thrown later in the application.
可以通过添加另一种方法来包装convert
来解决这个问题:
Fixing this problem can be achieved by adding another method to wrap 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);
这篇关于将列表值反映到另一个列表中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!