2

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

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

我可以想象,这个任务/习语在软件开发中经常出现,以至于它都被赋予了一个名称,并且还有可以为我自动完成它的现有库。你知道任何这样的图书馆吗?

4

5 回答 5

2

我不想要这样的图书馆。你的对象最终可能会有很多意想不到的状态。正如其他人所说,使用复制构造函数。

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

于 2013-02-02T22:17:07.653 回答
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可能是一个好的开始)。除了可能的性能问题(不知道这有多快)之外,我想的主要问题是这可能会导致您不希望复制的数据被复制,当多人处理相同的代码时尤其可能发生这种情况。

于 2013-02-02T22:03:51.143 回答
1

我不认为有一个通用的解决方案。也许AOP可以提供帮助,但这可能是一个不好的做法。

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

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

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

于 2013-02-02T22:07:05.910 回答
1

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

我使用过推土机——但又回到使用@dukeling 提到的复制构造函数。

于 2013-02-02T22:10:03.123 回答
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() );
}

}
于 2013-02-02T22:18:46.747 回答