我有一对类,其中一个字段是另一个字段的子集,超集类的getter都是可预测命名的(getFoo()
)。有没有办法有效地复制从超集类到子集类的所有公共字段,或者至少自动生成代码来执行此操作。
我应该注意:
编辑:一些简单的代码
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
答案 0 :(得分:12)
您可以使用Spring Framework中的BeanUtils
类来执行此操作。它可能不一定比基于反射的技术更有效,但编码肯定很简单。我希望您需要做的就是:
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
来迭代类的属性。这比使用低级反射API更简单。
答案 1 :(得分:3)
与第一个答案类似,但要澄清 - 不需要弹簧。 Commons BeanUtils.copy属性(Object dest,Object orig)
答案 2 :(得分:2)
如果您希望有效地完成任务(在运行时性能方面),那么使用getter和setter手动编写副本是可行的方法。除非getter或setter方法有些奇怪,否则它们的内部将被内联,以便它们与字段分配一样快。
反射方法(例如使用像BeanUtils
这样的现有类)编码较少,但可能比以简单方式调用getter和setter慢一个数量级。如果你试图自己实现这个,你可能会发现自己有更多的工作而不是你讨价还价,特别是如果你的反射副本类/方法必须处理重载方法,继承,价值转换,装箱/拆箱等等。
使用代码生成方法,您需要平衡实现代码生成(使用您选择的任何技术)的工作量和复杂性,以及手动编写复制方法的工作量。在20个课程之前,您可能不会使用代码生成方法实现收支平衡......如果您不熟悉该技术,可能会更多。
答案 3 :(得分:2)
要根据字段而不是getter和setter进行复制,您可以使用Spring ReflectionUtils.shallowCopyFieldState()。
答案 4 :(得分:1)
我会编写一个简单的java工具来自动生成类的源代码,这些类可以使用超集中的公共字段填充子集字段。此工具将使用反射来获取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
}
}
答案 5 :(得分:0)
您是否可以从应用中提供一些示例代码,说明您在帖子中提到的方案? 现在反射似乎是最好的方法,因为它允许你在运行时检查类成员。
答案 6 :(得分:0)
这显然是Java反思的任务,而其他人已经建议有效,虽然可能有点重量级的解决方案,这里还有一个:
大约一年前,我写了一个名为BeanPropertyController的小型JavaBean属性修饰符库。虽然我没有特别向任何人推荐它,但我确实认为库的同名类( see source )可以作为参考来采用类似的功能来满足您的需求。作为一个简单的例子,这里是我如何使用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
所以,我建议您转到我链接的网址,并根据您的需求调整这段代码。我很确定你不需要我包含的各种实例化方法,默认值提供者等。是的,可以认为BPC已被弃用。