Java 是否将列表值反映到另一个列表中? 列表列表a;名单b;

Java 是否将列表值反映到另一个列表中? 列表列表a;名单b;,java,reflection,Java,Reflection,我可以使用反射将listA反射到listB中吗?我得到了下面的代码,但只反映了一个对象 List <ClassA> listA; List <ClassB> listB; 公共静态B转换(一个实例, 类targetClass)引发异常{ B target=(B)targetClass.newInstance(); for(字段targetField:targetClass.getDeclaredFields()){ targetField.setAccessible(t

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

List <ClassA> listA; List <ClassB> listB;
公共静态B转换(一个实例,
类targetClass)引发异常{
B target=(B)targetClass.newInstance();
for(字段targetField:targetClass.getDeclaredFields()){
targetField.setAccessible(true);
场域=
实例.getClass().getDeclaredField(targetField.getName());
字段。setAccessible(true);
set(target,field.get(instance));
}
回报目标;
}
试试看

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

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;
}

看起来,您的两个
列表使用不同的泛型类型声明。因此,您将不得不使用不安全的强制转换。但这样做感觉非常错误。你到底想达到什么目的?如果列表中的对象类型应该不同,那么为什么要复制它们?

一般来说,
转换
方法不太可能工作(对于
列表
或任何其他类型)

调用
Field.setAccessible(true)
允许对私有字段进行读写访问,但不允许通过
Field.set()
修改
final
字段(引发
IllegalAccessException:Field为final
异常)

根据
List
的实现情况,您试图复制此文件可能会使其无法正常工作。例如,使用
ArrayList
,例如:

List list2 = new ArrayList(list1);
但是,下一个问题是
convert
方法正在执行浅拷贝。对于不同类型的
List
s,此修改版本的
convert
似乎可以正常工作,但它不会将列表中的
ClassA
对象转换为
ClassB
(上面未选中的强制转换隐藏了这一点)。这可能会导致应用程序稍后抛出
ClassCastException
s

通过添加另一个方法来包装
convert
,可以解决此问题:

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; 
}
publicstaticb转换器列表(
列表列表,类targetListClass,类targetClass)
抛出异常{
B targetList=targetListClass.newInstance();
对于(对象:列表){
add(convert(object,targetClass));
}
返回目标列表;
}
这将需要称为:

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 listB=(List)convertList(
listA,ArrayList.class,ClassB.class);

从技术上讲,是的,但仅在某些条件下。假设您想要将ClassA实例转换为ClassB实例。开始转换的代码行如下所示:

List<ClassB> listB = (List<ClassB>) convertList(
    listA, ArrayList.class, ClassB.class);
到目前为止我说的对吗

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

到目前为止还不错

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

ClassB bInstance = convert(aInstance, ClassB.class);
相同字段表示:相同字段名称和相同字段类型(或至少是“可浇铸”类型)


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

对不起,我没有注意到我的列表没有显示出来。基本上是两个接受不同类类型对象的列表实际上这两个类具有相同的属性,出于某种原因必须将ClassB转换为ClassA然后使用我给你的示例。如果编译器抱怨,使用castsYa这个我以前尝试过的方法,除了使用这个方法之外,还可以使用反射吗?你不需要使用反射。你可以,如果你愿意的话。检查其他问题以了解详细信息。不要这样做。你在这里做的事情非常奇怪。如果这两种类型有共同的操作,让它们实现一个共同的接口。嗨,Matthew Murdoch,你能向我解释一下,当反射列表时,复制serialVersionUID时为什么会失败,并且一个对象对一个对象不会出现此错误。你说的肤浅复制是什么意思?非常感谢你
ClassB bInstance = convert(aInstance, ClassB.class);
    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);
    }