根据o2的相应getter设置o1的所有setter

时间:2013-02-02 21:54:13

标签: java idioms

在Java中,我有一个方法可以根据对象to的相应属性修改对象from的属性。

public static void shape(SomeType from, SomeType to) {
    to.setA( from.getA() );
    to.setB( from.getB() );
    to.setC( from.getC() );
    ...
}

我可以想象这个任务/成语经常在软件开发中反复出现,它既有名字,也有现有的库,可以自动为我做这件事。你知道任何这样的图书馆吗?

5 个答案:

答案 0 :(得分:2)

我不想要这样的图书馆。您的对象最终可能会出现大量意外状态。正如其他人所说,使用Copy Constructor。

一般来说,如果你能负担得起,在转型国家时要争取不变。它通常使问题的推理更容易,并降低副作用的风险。一个很好的例子是joda time,它大量使用了不变性。

答案 1 :(得分:1)

通常的做法是使用复制构造函数或复制方法。

public SomeType(SomeType other)
{
  a = other.a;
  b = other.b;
  c = other.c;
}

public void copy(SomeType other)
{
  a = other.a;
  b = other.b;
  c = other.c;
}

我不确定是否有人会在实践中真正做到这一点,但理论上你可以使用反射来自动化这个过程(getMethods可能是一个好的开始)。除了可能出现的性能问题(不知道这有多快),我想到的主要问题是这可能导致你不想复制的数据被复制,特别是当多个人使用相同的代码时。

答案 2 :(得分:1)

我认为没有一般解决方案。也许AOP可能会有所帮助,但这可能是一种不好的做法。

如果要复制对象的所有数据并且它们属于同一个类,则该类的实现者可以实现Cloneable接口,您可以只调用clone()。

如果类不同,那么只有您知道源对象的哪些成员应该被复制到目标成员的哪些成员。并且逐个复制它们是最简单,最易读的方法。

还有一个“浅”或“深”的成员副本问题,超出了问题的范围,但值得记住。

答案 3 :(得分:1)

这已经在这里问过了。请看Copy all values from fields in one class to another through reflection

我使用了推土机 - 但是回到使用@dukeling所提到的复制构造器。

答案 4 :(得分:0)

尝试实现可克隆接口

public class SomeType implements Cloneable {
    private String a;

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public Object clone() {
        try {
            return super.clone();
        } catch(CloneNotSupportedException e) {
            System.out.println("Cloning not allowed.");
            return this;
        }
    } 
}

你可以测试一下这个::

public class Test {

    public static void main (String args[]) {
        SomeType a = new SomeType();
        SomeType b = (SomeType) a.clone();
        if ( a == b ) {
            System.out.println( "yes" );
        } else {
            System.out.println( "no" );
        }
    }

}

是的,如果对象类型不同,您可以尝试使用反射,但请记住,属性的名称必须相等

这是使用反射的答案,只要方法和属性的名称相同,使用此类就可以将所有参数从一个对象传递到另一个对象,而不管其类型如何。

package co.com;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class SetAttributes {

public static String capitalize( String word ) {
    return Character.toUpperCase( word.charAt( 0 ) ) + word.substring( 1 );
}

public static void setAttributes( Object from, Object to ) {
    Field [] fieldsFrom = from.getClass().getDeclaredFields();
    Field [] fielsdTo = to.getClass().getDeclaredFields();
    for (Field fieldFrom: fieldsFrom) {
        for (Field fieldTo: fielsdTo) {
            if ( fieldFrom.getName().equals( fieldTo.getName() ) ) {
                try {
                    Method [] methodsTo = to.getClass().getDeclaredMethods();
                    for ( Method methodTo: methodsTo ) {
                        if ( methodTo.getName().equals( "set" + capitalize( capitalize( fieldTo.getName() ) ) ) ) {
                            Method methodFrom = from.getClass().getDeclaredMethod( "get" + capitalize( fieldFrom.getName() ), null );
                            methodTo.invoke(to, methodFrom.invoke( from, null ) );
                            break;
                        }
                    }
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
            System.err.println( fieldFrom );
        }
    }
}

public static void main (String args[]) {
    SomeType a = new SomeType();
    SomeType b = new SomeType();
    a.setA( "This" );
    setAttributes( a, b );
    System.err.println( b.getA() );
}

}