复制java中类似类之间的字段

我有一对类,其中一个字段是另一个字段的子集,超集类的getter都是可预测命名的( getFoo() )。 有没有办法有效地将所有公共字段从超集类复制到子集类,或者至少自动生成代码来执行此操作。

我应该注意到:

  • 由于各种原因,我无法编辑超集类,也无法在整个过程中使用它们以避免必须进行数据复制。
  • 我可以在子集类中创建新方法,但我不能更改它们的字段。
  • 我们有几十个这样的对,有些类有很多字段,所以手工做这件事至少可以说是笨拙的。
  • 一位同事提出了一种创建generics复制方法的方法,该方法使用javareflection来获取任意两个类,以字符串forms迭代字符串,执行字符串操作以确定getter名称,然后执行它以自动设置字段子集类。 这很糟糕,但似乎有效。 我真的希望有更好的方法。

编辑:一些简单的代码请求

 public class SuperClass { private int foo; private int bar; private float bat; public int getFoo() { return foo; } public int getBar() { return bar; } public float getBat() { return bat; } } public class SubClass { private int foo; private float bat; } //wanted public static copySuperFieldsToSubMethod(Object super, Object sub) { ??? } // also acceptable would be some way to autogenerate all the assignment // functions needed 

您可以使用Spring Framework中的BeanUtils类来执行此操作。 它可能不一定比基于reflection的技术更有效,但编码肯定很简单。 我希望您需要做的就是:

 BeanUtils.copyProperties(source, target); 

有关此方法的Javadoc,请访问http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/BeanUtils.html#copyProperties(java.lang.Object,%20java。 lang.Object)

如果这不合适,您还可以考虑在Spring Framework中使用BeanWrapper / BeanWrapperImpl来迭代类的属性。 这比使用低级reflectionAPI更简单。

与第一个答案类似,但要澄清 – 不需要弹簧。 Commons BeanUtils.copy属性(Object dest,Object orig)

http://commons.apache.org/beanutils/api/org/apache/commons/beanutils/BeanUtils.html#copyProperties(java.lang.Object,%20java.lang.Object)

如果您希望有效地完成任务(在运行时性能方面),那么使用getter和setter手动编写副本是可行的方法。 除非有一些关于getter或setter方法的问题,否则它们的内部将被内联,以便它们与字段分配一样快。

reflection方法(例如使用像BeanUtils这样的现有类)编码较少,但可能比以简单方式调用getter和setter慢一个数量级。 如果你试图自己实现这个,你可能会发现自己有更多的工作,特别是如果你的reflection副本类/方法必须处理重载方法,inheritance,价值转换,装箱/拆箱等等。

使用代码生成方法,您需要平衡实现代码生成(使用您选择的任何技术)的工作量和复杂性与手动编写复制方法的努力。 在20个课程之前,你可能不会使用代码生成方法来解决这个问题……如果你不熟悉这个技术,还有更多。

要基于字段而不是getter和setter进行复制,可以使用Spring的ReflectionUtils.shallowCopyFieldState() 。

我写了一个简单的java工具来自动生成类的源代码,这些类可以使用超集中的公共字段填充子集字段。 此工具将使用reflection来获取getter和setter方法的名称。 其余的是(普通的)String操作,用于在内存中“写”源文件并将其存储到*.java文件中。 编译所有这些自动生成的文件,并将类文件添加到类路径中。

这个类看起来像这样:

 class AClassToBClassPopulator implements Populator { @Overwrite public void populate(Object superSet, Object subSet) { subSet.setFieldA(superSet.getFieldA()); subSet.setFieldB(superSet.getFieldB()); // .. and so on. The method body is created through reflection } } 

您能否从应用中提供一些示例代码,描述您在post中提到的方案? 现在reflection似乎是最好的方法,因为它允许您在运行时检查类成员。

这显然是Java反思的任务,虽然其他人已经建议有效,虽然可能有点重量级解决方案,这里还有一个:

大约一年前,我写了一个名为BeanPropertyController的小型JavaBean属性修饰符库。 虽然我没有特别推荐给任何人,但我确实认为库的同名类( 参见源代码 )可以作为参考来采用类似的function来满足您的需求。 作为一个简单的例子,这里是我如何使用BPC( 几乎! )你所要求的:

 // somewhere in code... SuperClass a = new SuperClass(); a.foo = 101; a.bar = 102; a.bat = 103f; SubClass b = new SubClass(); b.foo = 201; b.bat = 202f; BeanPropertyController fromB = BeanPropertyController.of(b, ExtractionDepth.QUESTIMATE); BeanPropertyController toA = BeanPropertyController.of(a, ExtractionDepth.QUESTIMATE); // This is where the magic happens: for (String propertyName : fromB.getPropertyNames()) { toA.mutate(propertyName, fromB.access(propertyName)); } a = (SuperClass) toA.getObject(); b = (SubClass) fromB.getObject(); System.out.println("SuperClass' foo="+a.foo+" bar="+a.bar+" bat="+a.bat); System.out.println("SubClass' foo="+b.foo+" bat="+b.bat); 

打印出来

 SuperClass' foo=201 bar=102 bat=202.0 SubClass' foo=201 bat=202.0 

所以,我建议你去我链接的URL,并根据你的需要调整这段代码。 我很确定你不需要我包含的各种实例化方法,默认值提供者等。 是的,可以认为BPC已被弃用。