java 两个对象合并_关于反射:在Java中合并两个对象

我有两个相同类型的对象。

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}

您能描述一下这个"合并"对象的外观吗?

如果obj1.a ="George"和obj2.a ="Lucas"在"合并"对象中的obj3.a值应该是什么?

您可以假设对象是互斥的

只要您具有自己的getter和setter的POJO都可以使用。该方法使用update中的非空值更新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();

}

}

}

}

感谢您的回答...但是我的对象有很多原始类型,例如int,float e.t.c.它还具有列表作为成员。

没关系。只要两个对象都具有getXX及其对应的setXX,这将起作用。它将仅使用getter和setter复制值

使用obj.getClass()。getDeclaredMethods()跳过getClass / setClass等,仅获取在该类或相应接口中定义的方法。

我对第一个if感到困惑。试图达到什么目的?

它不应该返回对象吗?

@jon函数更新obj参数对象,以便将所有更改保存到obj实例中,而不是返回更新的对象。您可以在函数末尾返回obj,但这不是必需的。

String toName = fromName.replace("get","set");如果我的字段名称为thisisfieldsetted会怎样?

通常,此代码一目了然。必须有一种更好的方式来编写此代码。因此,我是Zons的粉丝,请在下面回答。

也许像

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对象,而不是修改当前对象。

那就是我要建议的-无论如何,您都必须在任何地方清楚地编写规则-除非绝对不得已,否则您不想在代码中添加" Magic"之类的反射,并且这种情况绝不那么困难。

NullPointerException,因为this.b可能是null,并且没有满足b的"来自obj2的相同数组列表"的请求

我正在使用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

}

}

只是容纳布尔同步。区分大小写(驼色表示法)

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;

}

如果为属性创建获取器和设置器,则可以使用Commons BeanUtils中的copyProperties方法。

在非常特殊的情况下,您似乎想要一个新的对象,该对象从两个实例中获取真实值。这是实现该目的的实现。该方法应该添加到类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;

}

将此方法添加到您的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.

}

}

}

}

}

如果您不想在添加/删除字段等时不断维护该方法,这是最好的解决方案。Id可以走得更远,不要忽略" IllegalAccessException",因为它可能会隐藏问题,但是对于某些特定字段,您有不想使用的替代情况合并-或者您想以其他方式处理等

有一个动态解决方案可以合并需要反射和递归的任何两个对象。

public < T > T merge(T local, T remote, ArrayList 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;

}

变量说明:

local:另一个对象将合并到的对象

remote:将合并到本地对象的对象

listOfClass:给定对象中的自定义类的ArrayList

该函数返回一个合并的对象,很好。

荣誉! :)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值