我有这个问题。但我很难解释,因为我不知道要使用的确切术语。希望有人会理解。我会尽力描述。我觉得这与
parsing
有很大关系
假设有两个班级。在这两个类中我都有一些变量,比如字符串(为了简单起见,变量类型可以是任何类型),它们具有相似的名称.
Eg:
class ClassA{
String x,y,z;
}
class ClassB{
String x,y,z;
}
现在,我需要的是,我需要将一个类的变量值复制到其他类对应的变量中。
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;
那样。
但请注意,我需要的不是上述方法。我希望有一种方法可以编写一个简单的方法,以便它可以通过传递给它的名称来识别相关变量。然后它会相应地进行值分配。
我想象中的方法是这样的,
void assign(String val){
// aa.<val>=val
}
例如,如果您将
bb.x
传递给 assign(...)
方法,那么它将执行 aa.x=bb.x
赋值。
希望这已经足够清楚了。必须有更好的方法来解释这一点。如果有人知道,请编辑帖子(+标题)以使其更清楚(但保留我的想法)..
如果有办法实现这一点,请告诉我。
谢谢!
Dozer 很好,请参阅 Jean-Remy 的回答。
此外,如果变量根据 JavaBeans 标准具有 getter 和 setter,则有许多技术可以帮助您,例如Apache Commons / BeanUtils
示例代码(未测试):
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());
}
更新:
如果您没有 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;
}
}
调用语法:
Copier.copy(sourceObject, targetObject);
你听说过推土机吗? : http://dozer.sourceforge.net/
推土机
Dozer 是一个 Java Bean 到 Java Bean 映射器,它递归地将数据从一个对象复制到另一个对象。通常,这些 Java Bean 将具有不同的复杂类型。
Dozer 支持简单属性映射、复杂类型映射、双向映射、隐式-显式映射以及递归映射。这包括映射集合属性,这些属性也需要在元素级别进行映射。
Dozer 允许您映射 Java Beans:
这里是图书馆网站上的 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>
这会将对象 org.dozer.vo.TestObject 映射到 TestObjectPrime,将所有相同的变量映射到一起(就像您的情况一样),并将变量 TestObjectFoo.oneFoo 映射到 TestObjectFooPrime.oneFooPrime。
太好了,不是吗?
看这里。只需使用
BeanUtils.copyProperties(newObject, oldObject);
新答案
我建议调查多佛,因为它看起来很简单。
第二个选项是将类序列化为 XML 并仅在匹配的成员上反序列化为目标类。
我在评论中提到的第三个选项是使用反射 - http://java.sun.com/developer/technicalArticles/ALT/Reflection/
这种技术允许一个很好的设计模式称为内省 - Java 内省和反射 反过来允许你发现某个类的成员......
现在,话虽如此,我们可以简单地“发现”ClassA 的成员,用他们的名字填充 ArrayList,发现 ClassB 的成员,用他们的名字填充另一个 ArrayList,并复制相交集的值。至少那是我的想法。