java - 如何用另一个 java 对象的值更新一个 java 对象的所有字段?
问题描述
假设以下类:
public class TestClass {
String attr1;
String attr2;
String attr3;
}
和一个客户端代码,如:
final TestClass testClassA = new TestClass();
testClassA.attr1 = "1";
testClassA.attr1 = "2";
testClassA.attr1 = "3";
final TestClass testClassB = new TestClass();
我想找到更新testClassB
所有值的方式/方法testClassA
。
testClassB.updateAll(testClassA)
一种这样的解决方案是:
public void updateAll(TestClass testClass) {
this.attr1 = testClass.attr1;
this.attr2 = testClass.attr2;
this.attr3 = testClass.attr3;
}
现在,事情来了:我希望不必手动编写此方法,以便在添加新属性时降低弹性。在这种情况下,我可能会忘记将其添加到更新方法中。
该解决方案不需要直接分配值,实际上我更喜欢它调用 setter 方法。
我也可以使用任何第三方框架,比如 Lombok。我正在寻找类似的东西@RequiredArgsConstructor
,但是我需要更新而不是创建新对象。
所以类似 a@RequiredArgsSetter
或Object.updateInto(Object1 o, Object2 o)
方法的东西,但同样,它不应该创建一个新对象,而只是简单地更新现有对象的所有字段。
奖励积分,如果可以以某种方式注释应该包含或排除在设置中的字段。
解决方案
我发现您的问题很有趣,并决定尝试一下。这是使用反射的解决方案。它查找按名称和类型匹配且未被注释排除的字段,然后设置任何匹配字段的值。
免责声明:我没有彻底测试过这个,只是轻轻地。它可能需要一些工作。它也不使用 setter 方法,而只是设置字段值。
属性复制方法:
public class AttrCopy {
public void copyAttributes(Object from, Object to) throws IllegalAccessException {
Map<String, Field> toFieldNameMap = new HashMap<>();
for(Field f : to.getClass().getDeclaredFields()) {
toFieldNameMap.put(f.getName(), f);
}
for(Field f : from.getClass().getDeclaredFields()) {
Field ff = toFieldNameMap.get(f.getName());
f.setAccessible(true);
boolean include = f.getDeclaredAnnotation(AttrCopyExclude.class) == null;
if(include && ff != null && ff.getType().equals(f.getType())) {
ff.setAccessible(true);
ff.set(to, f.get(from));
}
}
}
}
排除字段的注释:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AttrCopyExclude {
}
测试类:
public class ClassA {
private String attribute1;
private int attribute2;
private int attribute3;
private String attribute4;
private String attribute5;
// toString()
}
public class ClassB {
private String attribute1;
private int attribute2;
private String attribute3;
@AttrCopyExclude
private String attribute4;
private String attribute6;
// toString()
}
测试代码:
public class Tester {
public static void main(String[] args) throws IllegalAccessException {
ClassA classA = new ClassA("aaa", 123, 456, "ddd", "eee");
ClassB classB = new ClassB("111", 789, "333", "444", "555");
System.out.println("Before");
System.out.println(classA);
System.out.println(classB);
new AttrCopy().copyAttributes(classB, classA);
System.out.println("After copy A -> B");
System.out.println(classA);
System.out.println(classB);
}
}
测试输出:
Before
ClassA{attribute1='aaa', attribute2=123, attribute3=456, attribute4='ddd', attribute5='eee'}
ClassB{attribute1='111', attribute2=789, attribute3='333', attribute4='444', attribute6='555'}
After copy B -> A
ClassA{attribute1='111', attribute2=789, attribute3=456, attribute4='ddd', attribute5='eee'}
ClassB{attribute1='111', attribute2=789, attribute3='333', attribute4='444', attribute6='555'}
复制属性 1 和 2。3 被排除,因为类型不匹配。4被注释排除。最后一个被排除,因为名称不匹配。
推荐阅读
- javascript - 记住上次悬停的 Div
- delphi - 如何在 TWebBrowser 或 TImage 中加载 base64 加密的 url?
- vue.js - 如何重用应该使用唯一 vuex 存储实例的组件
- azure - 在返回 ServiceBus 消息的 Azure 函数中,如何有条件地返回消息?
- php - Get_Header 在主页 Wordpress 上不起作用 - 几乎所有东西都试过了
- r - R中多列的条件均值?
- google-tag-manager - 通过 Google 跟踪代码管理器跟踪 Pardot 表单提交
- python - 从 python 中的 factor_analysisr 计算拟合优度和 rmsea
- php - 异常“无法在 BinaryFileResponse 实例上设置内容。” 仅在生产服务器上抛出
- php - 我在解析 php sdk 时遇到问题