将列表值反映到另一个列表中? [英] Reflect a list value into another list?

查看:35
本文介绍了将列表值反映到另一个列表中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 方法不太可能工作(对于 Lists 或任何其他类型).

In general the convert method is not likely to work (for Lists 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 时失败.

对已发布代码的以下更改解决了 ArrayListstatic 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 方法正在执行浅拷贝.对于不同类型的 Lists,这个修改过的 convert 版本可能看起来工作正常,但它不会将列表中的 ClassA 对象转换为 ClassB(上面未经检查的强制转换隐藏了这一点).这可能会导致 ClassCastException 稍后在应用程序中抛出.

However, the next problem is that the convert method is performing a shallow copy. For Lists 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 ClassCastExceptions 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆