我有两个相同类型的对象。
Class A{
String a;
List b;
int c;
}
A obj1= new A();
A obj2 = new A();
obj1 => {a = "hello";b=null;c=10}
obj2 => {a=null;b= new ArrayList();c=default value}
请告诉我将这些对象组合成单个对象的最佳方法是什么?
obj3 = {a = "hello";b=(same arraylist from obj2);c=10}
答案 0 :(得分:23)
只要您拥有自己的getter和setter的POJO,这就有效。该方法使用更新中的非空值更新 obj 。它在 obj 上调用setParameter(),并在更新上调用getParameter()的返回值:
public void merge(Object obj, Object update){
if(!obj.getClass().isAssignableFrom(update.getClass())){
return;
}
Method[] methods = obj.getClass().getMethods();
for(Method fromMethod: methods){
if(fromMethod.getDeclaringClass().equals(obj.getClass())
&& fromMethod.getName().startsWith("get")){
String fromName = fromMethod.getName();
String toName = fromName.replace("get", "set");
try {
Method toMetod = obj.getClass().getMethod(toName, fromMethod.getReturnType());
Object value = fromMethod.invoke(update, (Object[])null);
if(value != null){
toMetod.invoke(obj, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
答案 1 :(得分:8)
也许像
class A {
String a;
List<..> b;
int c;
public void merge(A other) {
this.a = other.a == null ? this.a : other.a;
this.b.addAll(other.b);
this.c = other.c == 0 ? this.c : other.c;
}
}
A a1 = new A();
A a2 = new A();
a1.a = "a prop";
a2.c = 34;
a1.merge(a2);
A.merge
可能会返回一个新的A
对象,而不是修改当前对象。
答案 2 :(得分:6)
只是容纳布尔同步。区分大小写(骆驼表示法)
public boolean merge(Object obj){
if(this.equals(obj)){
return false;
}
if(!obj.getClass().isAssignableFrom(this.getClass())){
return false;
}
Method[] methods = obj.getClass().getMethods();
for(Method fromMethod: methods){
if(fromMethod.getDeclaringClass().equals(obj.getClass())
&& (fromMethod.getName().matches("^get[A-Z].*$")||fromMethod.getName().matches("^is[A-Z].*$"))){
String fromName = fromMethod.getName();
String toName ;
if(fromName.matches("^get[A-Z].*")){
toName = fromName.replace("get", "set");
}else{
toName = fromName.replace("is", "set");
}
try {
Method toMetod = obj.getClass().getMethod(toName, fromMethod.getReturnType());
Object value = fromMethod.invoke(this, (Object[])null);
if(value != null){
toMetod.invoke(obj, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return true;
}
答案 3 :(得分:6)
我正在使用Spring Framework。我在一个项目上遇到了同样的问题 为了解决这个问题,我使用了课程BeanUtils和上面的方法
public static void copyProperties(Object source, Object target)
这是一个例子,
public class Model1 {
private String propertyA;
private String propertyB;
public Model1() {
this.propertyA = "";
this.propertyB = "";
}
public String getPropertyA() {
return this.propertyA;
}
public void setPropertyA(String propertyA) {
this.propertyA = propertyA;
}
public String getPropertyB() {
return this.propertyB;
}
public void setPropertyB(String propertyB) {
this.propertyB = propertyB;
}
}
public class Model2 {
private String propertyA;
public Model2() {
this.propertyA = "";
}
public String getPropertyA() {
return this.propertyA;
}
public void setPropertyA(String propertyA) {
this.propertyA = propertyA;
}
}
public class JustATest {
public void makeATest() {
// Initalize one model per class.
Model1 model1 = new Model1();
model1.setPropertyA("1a");
model1.setPropertyB("1b");
Model2 model2 = new Model2();
model2.setPropertyA("2a");
// Merge properties using BeanUtils class.
BeanUtils.copyProperties(model2, model1);
// The output.
System.out.println("Model1.propertyA:" + model1.getPropertyA(); //=> 2a
System.out.println("Model1.propertyB:" + model1.getPropertyB(); //=> 1b
}
}
答案 4 :(得分:3)
如果为属性创建getter和setter,则可以使用Commons BeanUtils中的copyProperties方法。
答案 5 :(得分:2)
在您非常特殊的情况下,您似乎想要一个新对象,它从两个实例中获取真实值。这是一个可以实现的实现。该方法应添加到类A
,以便它可以访问字段。
public A specialMergeWith(A other) {
A result = new A();
result.a = (a == null ? other.a : a);
result.b = (b == null ? other.b : b);
result.c = (c == DEFAULT_VALUE ? other.c : c);
return result;
}
答案 6 :(得分:0)
将此方法添加到您的POJO 中,然后像myObject.merge(newObject)
一样使用它。它使用泛型来遍历POJO的字段,因此您不要提及任何字段名:
/**
* Fill current object fields with new object values, ignoring new NULLs. Old values are overwritten.
*
* @param newObject Same type object with new values.
*/
public void merge(Object newObject) {
assert this.getClass().getName().equals(newObject.getClass().getName());
for (Field field : this.getClass().getDeclaredFields()) {
for (Field newField : newObject.getClass().getDeclaredFields()) {
if (field.getName().equals(newField.getName())) {
try {
field.set(
this,
newField.get(newObject) == null
? field.get(this)
: newField.get(newObject));
} catch (IllegalAccessException ignore) {
// Field update exception on final modifier and other cases.
}
}
}
}
}
答案 7 :(得分:0)
有一个动态解决方案可以合并需要反射和递归的任何两个对象。
public <T> T merge(T local, T remote, ArrayList<String> listOfClass)
throws IllegalAccessException, InstantiationException {
Class<?> clazz = local.getClass();
Object merged = clazz.newInstance();
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
Object localValue = field.get(local);
Object remoteValue = field.get(remote);
if (localValue != null) {
if (listOfClass.contains(localValue.getClass().getSimpleName())) {
field.set(merged, this.merge(localValue, remoteValue, listOfClass));
} else {
field.set(merged, (remoteValue != null) ? remoteValue : localValue);
}
} else if (remoteValue != null) {
field.set(merged, remoteValue);
}
}
return (T) merged;
}
变量说明:
该函数返回一个合并的对象,很好。
荣誉! :)