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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11900429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 06:50:16  来源:igfitidea点击:

Copying one class's fields into another class's identical fields

javaparsingjavabeansdozer

提问by Sumudu

I have this question. But it will be difficult for me to explain as I don't know exact terms to use. Hope someone will understand. I'll try to discribe to the best i can. I feel like this is much related to parsing

我有这个问题。但我很难解释,因为我不知道要使用的确切术语。希望有人能理解。我会尽力描述。我觉得这与parsing

Say there are two classes. And in both classes I have some variables, say strings (just for simplicity, variable type can be any), which have similar names.

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

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

    class ClassB{
        String x,y,z;
    }

Now, what i need is, i need to copy the value of one class's variable values to other classes corresponding variable.

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

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;

like that.

像那样。

But please note that what i need is not the above method. I hope there will be a way to write a simple method, so that it will identify the relevent variable by the name passed to it. Then it will do the value assignment accordingly.

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

My imagined method is like this,

我想象的方法是这样的,

void assign(String val){        
    // aa.<val>=val
}

For example if you pass bb.xto assign(...)method, then it will do aa.x=bb.xassignment.

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

Hope this is clear enough. There must be a better way to explain this. If someone know it please edit the post(+title) to make it more clear (But save my idea)..

希望这已经足够清楚了。必须有更好的方法来解释这一点。如果有人知道,请编辑帖子(+标题)以使其更清楚(但请保留我的想法)。

Please let me know if there's a way to achieve this.

请让我知道是否有办法实现这一目标。

Thanks!

谢谢!

回答by Sean Patrick Floyd

Dozer is fine, see Jean-Remy's answer.

推土机很好,请参阅让-雷米的回答。

Also, if the variables have getters and setters according to the JavaBeans standard, there are a number of technologies that could help you, e.g. Apache Commons / BeanUtils

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

Sample code (not tested):

示例代码(未测试):

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

Update:

更新:

If you don't have getters and setters, here's a quick hack that copies field values from one class to another as long as the fields have common names and types. I haven't tested it, but it should be OK as a starting point:

如果您没有 getter 和 setter,这里有一个快速技巧,只要字段具有通用名称和类型,就可以将字段值从一个类复制到另一个类。我还没有测试过,但作为起点应该可以:

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

Call Syntax:

调用语法:

Copier.copy(sourceObject, targetObject);

回答by Jean-Rémy Revy

Did you ever heared about Dozer ? : http://dozer.sourceforge.net/

你听说过推土机吗?:http: //dozer.sourceforge.net/

Dozer

Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another. Typically, these Java Beans will be of different complex types.

Dozer supports simple property mapping, complex type mapping, bi-directional mapping, implicit-explicit mapping, as well as recursive mapping. This includes mapping collection attributes that also need mapping at the element level.

推土机

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

Dozer 支持简单属性映射、复杂类型映射、双向映射、隐式-显式映射以及递归映射。这包括也需要在元素级别映射的映射集合属性。

Dozer allow you to map Java Beans :

Dozer 允许您映射 Java Bean:

  • using their names (implicit mapping), i.e mapping ClassA.x to ClassB.x
  • providing hability to map diffrent structures (explicit mapping) with different names with (quite simple) xml or annoation configuration .
  • 使用它们的名称(隐式映射),即将 ClassA.x 映射到 ClassB.x
  • 提供使用(非常简单)xml 或注释配置映射具有不同名称的不同结构(显式映射)的能力。

Here a XML example on the library site :

这是图书馆网站上的 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>

This will map object org.dozer.vo.TestObject into TestObjectPrime, mapping all variable that are identicals together (like in your case) and variables TestObjectFoo.oneFoo into TestObjectFooPrime.oneFooPrime.

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

Great, isn't it ?

很棒,不是吗?

回答by Shark

new answer.

新答案。

I'd suggest looking into Dover as it seems pretty straightforward.

我建议调查 Dover,因为它看起来很简单。

The second option is serializing classes into XML and deserializing into your target class only on members that match.

第二个选项是将类序列化为 XML 并仅在匹配的成员上反序列化为目标类。

The third option I mentioned in the comment was using reflection - http://java.sun.com/developer/technicalArticles/ALT/Reflection/

我在评论中提到的第三个选项是使用反射 - http://java.sun.com/developer/technicalArticles/ALT/Reflection/

This technique allows for a nice design pattern called Introspection - Java introspection and reflectionwhich in turn allows you to discover members of a certain class...

这种技术允许一个很好的设计模式叫做自省——Java 自省和反射,反过来又允许你发现某个类的成员......

Now, having said that, one would simply "discover" members of ClassA, fill a ArrayList with their names, discover members of ClassB, fill another ArrayList with their names, and copy values of the intersecting set. At least that's my idea on it.

现在,话虽如此,可以简单地“发现”ClassA 的成员,用他们的名字填充一个 ArrayList,发现 ClassB 的成员,用他们的名字填充另一个 ArrayList,并复制相交集的值。至少这是我的想法。

回答by Dmitry

Look here. Just use BeanUtils.copyProperties(newObject, oldObject);

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