将列表值反映到另一个列表中?

List  listA; List  listB; 

我可以使用reflection将listA反映到listB中吗? 我得到了下面的代码但只反映了一个对象

 public static  B convert(A instance, Class 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或任何其他类型)。

调用Field.setAccessible(true)允许对私有字段进行读写访问,但不允许通过Field.set()修改final字段( IllegalAccessException: Field is final是抛出的IllegalAccessException: Field is finalexception)。

根据List的实现,您尝试复制它可能会阻止它正常工作。 例如,使用ArrayList例如:

 // Note that this is an unchecked cast List listB = (List) convert(listA, ArrayList.class); 

尝试复制serialVersionUID时失败。

对于ArrayList static final serialVersionUID ,对已发布代码的以下更改将解决此问题:

 public static  B convert(A instance, Class 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 ,这个改变版本的convert可能看起来工作正常但它不会将列表中的ClassA对象转换为ClassB (上面未经检查的强制转换隐藏了这个)。 这可能会导致稍后在应用程序中抛出ClassCastException

修复此问题可以通过添加另一个方法来包装convert来实现:

 public static , C> B convertList( List list, Class targetListClass, Class targetClass) throws Exception { B targetList = targetListClass.newInstance(); for (A object : list) { targetList.add(convert(object, targetClass)); } return targetList; } 

然后需要将其称为:

 List listB = (List) convertList( listA, ArrayList.class, ClassB.class); 

试试吧。

但它不是必需的。 您只需将第一个列表的内容添加到第二个列表:

 List list2 = new ArrayList(list1); 

看起来,你的两个List声明了不同的generics类型。 所以你将不得不使用不安全的演员阵容。 但这样做感觉非常糟糕。 你究竟想要实现什么目标? 如果列表中的对象类型应该不同,那么为什么要尝试复制它们呢?

技术上说,是的,但仅限于某些条件。 假设您要将ClassA实例转换为ClassB实例。 开始转换的代码行如下:

 ClassB bInstance = convert(aInstance, ClassB.class); 

到目前为止我是否正确?

上面的代码将(1)创建一个新的ClassB对象,使用它的默认构造函数,(2)获取在ClassB上声明的所有字段(但没有来自任何ClassB超类型的字段!),(3)从ClassA和(4)获取相同的字段)将值从aInstance设置为新创建的ClassB实例中的字段。

到现在为止还挺好。

但是这只有当且仅当ClassA与ClassB具有完全相同的字段时才会起作用(它可能有更多字段)。 这是限制。 如果ClassA和ClassB不满足此前提条件,则必须分别捕获exception并处理这些情况,例如:

  try { Field field = instance.getClass().getDeclaredField(targetField.getName()); field.setAccessible(true); try { targetField.set(target, field.get(instance)); } catch (IllegalArgumentException e) { handleIncompatibleType(target, targetField, field.get(instance)); } } catch (NoSuchFieldException e) { handleMissingFieldInA(instance, targetField); } 

相同字段表示:相同的字段名称和相同的字段类型(或至少是“可转换”类型)

因此,如果您有List但需要List ,则可以遍历第一个列表,将List项转换为ClassB对象并将它们写入目标列表。