将一个类的字段复制到另一个类的相同字段中

Sum*_*udu 9 java parsing javabeans dozer

我有这个问题.但是我很难解释,因为我不知道使用的确切术语.希望有人能理解.我会试着尽力而为.我觉得这与此有很大关系parsing

说有两个班.在这两个类中我都有一些变量,比如字符串(只是为了简单起见,变量类型可以是任何变量),它们具有相似的名称.

Eg:
    class ClassA{
        String x,y,z;
    }

    class ClassB{
        String x,y,z;
    }
Run Code Online (Sandbox Code Playgroud)

现在,我需要的是,我需要将一个类的变量值的值复制到其他类对应的变量.

Eg:
    ClassA aa=new ClassA();
    ClassB bb=new ClassB();
    //set bb's variables
    aa.x=bb.x;
    aa.y=bb.y;
    aa.z=bb.z;
Run Code Online (Sandbox Code Playgroud)

像那样.

但请注意,我需要的不是上述方法.我希望有一种方法可以编写一个简单的方法,以便它通过传递给它的名称来识别相关变量.然后它会相应地进行值赋值.

我想象的方法是这样的,

void assign(String val){        
    // aa.<val>=val
}
Run Code Online (Sandbox Code Playgroud)

例如,如果您传递bb.xassign(...)方法,那么它将进行aa.x=bb.x分配.

希望这很清楚.必须有更好的方法来解释这一点.如果有人知道,请编辑帖子(+标题)以使其更清晰(但保存我的想法)..

如果有办法实现这一点,请告诉我.

谢谢!

Sea*_*oyd 11

推土机很好,请参阅Jean-Remy的回答.

此外,如果变量根据JavaBeans标准具有getter和setter,那么有许多技术可以帮助您,例如Apache Commons/BeanUtils

示例代码(未测试):

final Map<String, Object> aProps = BeanUtils.describe(a);
final Map<String, Object> bProps = BeanUtils.describe(b);
aProps.keySet().retainAll(bProps.keySet());
for (Entry<String, Object> entry : aProps.entrySet()) {
    BeanUtils.setProperty(b,entry.getKey(), entry.getValue());
}
Run Code Online (Sandbox Code Playgroud)

更新:

如果你没有getter和setter,只要字段有通用的名称和类型,这里就是一个快速的hack,它将字段值从一个类复制到另一个类.我还没有测试过,但它应该是一个好的起点:

public final class Copier {

    public static void copy(final Object from, final Object to) {
        Map<String, Field> fromFields = analyze(from);
        Map<String, Field> toFields = analyze(to);
        fromFields.keySet().retainAll(toFields.keySet());
        for (Entry<String, Field> fromFieldEntry : fromFields.entrySet()) {
            final String name = fromFieldEntry.getKey();
            final Field sourceField = fromFieldEntry.getValue();
            final Field targetField = toFields.get(name);
            if (targetField.getType().isAssignableFrom(sourceField.getType())) {
                sourceField.setAccessible(true);
                if (Modifier.isFinal(targetField.getModifiers())) continue;
                targetField.setAccessible(true);
                try {
                    targetField.set(to, sourceField.get(from));
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Can't access field!");
                }
            }
        }
    }

    private static Map<String, Field> analyze(Object object) {
        if (object == null) throw new NullPointerException();

        Map<String, Field> map = new TreeMap<String, Field>();

        Class<?> current = object.getClass();
        while (current != Object.class) {
            for (Field field : current.getDeclaredFields()) {
                if (!Modifier.isStatic(field.getModifiers())) {
                    if (!map.containsKey(field.getName())) {
                        map.put(field.getName(), field);
                    }
                }
            }
            current = current.getSuperclass();
        }
        return map;
    }
}
Run Code Online (Sandbox Code Playgroud)

调用语法:

Copier.copy(sourceObject, targetObject);
Run Code Online (Sandbox Code Playgroud)

  • 效果很好!它缺少"current = current.getSuperclass();" 在"while(current!= Object.class)"循环结束时.没有它,它会进入无限循环. (2认同)

Jea*_*evy 7

你有没有听说过Dozer?:http://dozer.sourceforge.net/

推土机

Dozer是Java Bean到Java Bean映射器,它以递归方式将数据从一个对象复制到另一个对象.通常,这些Java Bean将具有不同的复杂类型.

Dozer支持简单属性映射,复杂类型映射,双向映射,隐式显式映射以及递归映射.这包括映射还需要在元素级别进行映射的集合属性.

推土机允许您映射Java Bean:

  • 使用它们的名称(隐式映射),即将ClassA.x映射到ClassB.x.
  • 提供使用(非常简单的)xml或annoation配置来映射具有不同名称的不同结构(显式映射)的能力.

这是库站点上的XML示例:

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net
          http://dozer.sourceforge.net/schema/beanmapping.xsd">

  <mapping> 
    <class-a>org.dozer.vo.TestObject</class-a>
    <class-b>org.dozer.vo.TestObjectPrime</class-b>   
    <field>
      <a>one</a>
      <b>onePrime</b>
    </field>
  </mapping>  

      <!-- SNIP ... -->

</mappings>
Run Code Online (Sandbox Code Playgroud)

这会将对象org.dozer.vo.TestObject映射到TestObjectPrime,将所有相同的变量(如您的情况)和变量TestObjectFoo.oneFoo映射到TestObjectFooPrime.oneFooPrime.

太棒了,不是吗?


Dmi*_*try 5

这里。只需使用BeanUtils.copyProperties(newObject, oldObject);