我正在编写一些完全动态的方法,其中需要比较两个不同类的对象。
以下是对象的示例:
public class Object1 {
private String lastname;
private String firstname;
private int age;
private int gender;
//All getters and setters
}
public class Object2 {
private String lastname;
private String address;
private String job;
//All getters and setters
}
如您在此处看到的,唯一的公共属性是姓氏,所以我希望我的比较仅适用于姓氏
另外:
因此,我正在寻找类似于BeanUtils的类,该类具有用于通用属性的copyProperties方法,但是在这里,我不想比较复制。
我认为这种实用程序类可能存在,但找不到。
所以,如果您有个主意,我会很乐意阅读:)
谢谢!
[编辑1]有关为什么要这样做的更多信息:
我正在编写一个通用系统,以基于JAX-RS(Jersey)为REST Api生成端点。 我正在使用具有类似«simple»示例之类的泛型类型的接口:
public interface sampleEndpoint<BEANPARAM,BODYREQUEST,RESPONSE> {
@PUT
@Path("/{id}")
default RESPONSE update(@Valid @BeanParam BEANPARAM bp, @Valid BODYREQUEST body) {
//Check if id in path is the same as id in the body
....
}
}
(对于Jersey,我们不能使用BeanParam在同一个Bean PathParam,QueryParam和RequestBody中进行检索。这就是为什么我需要同时使用BeanParam和另一个Bean作为主体)
我的用例可能更复杂,但这只是一个简单的例子。
答案 0 :(得分:0)
根据我的收集,看来Reflection API正是您所需要的。您可以获取每个类中所有Fields的列表,然后仅比较两个具有相同名称的字段的值。
此方法的主要优点是可以将其推广到任意两个类。但是,Reflection常常令人讨厌,因为它破坏了封装,我建议您在解决此问题之前,针对您的问题寻求更好的解决方案。
答案 1 :(得分:0)
我最终创建了自己的课堂来实现我想要的。
我决定使用jackson(fasterxml)在JsonNode中转换我的对象,然后递归比较JsonNodes。
这是代码(我需要做一些测试以更深入地验证它,但它适用于我的用例):
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Iterator;
public class ObjectComparator {
/**
* For each attribute of «expected» Object, verify if this attribute exists in «actual» and if it exists, verify if the value is the same as the «expected» one
*
* @param expected : the reference JsonNode
* @param actual : the Object in which we want to verify the attributes
* @return true if all commons attributes between «expected» and «actual» have same values, otherwise returns false
*/
public static boolean CommonsAttributesComparator(Object expected, Object actual) {
ObjectMapper mapper = new ObjectMapper();
JsonNode expectedNode = mapper.convertValue(expected, JsonNode.class);
JsonNode actualNode = mapper.convertValue(actual, JsonNode.class);
return(JsonNodeComparator(expectedNode, actualNode));
}
/**
* For each attribute of «expected» JsonNode, verify if this attribute exists in «actual» and if it exists, verify if the value is the same as the «expected» one
*
* @param expectedNode : the reference JsonNode
* @param actualNode : the JsonNode in which we want to verify the attributes
* @return true if all commons attributes between «expected» and «actual» have same values, otherwise returns false
*/
public static boolean JsonNodeComparator(JsonNode expectedNode, JsonNode actualNode) {
Iterator<String> expectedKeys = expectedNode.fieldNames();
if(!expectedKeys.hasNext()) {
return expectedNode.equals(actualNode);
}
while (expectedKeys.hasNext()) {
String currentKey = expectedKeys.next();
if (
!expectedNode.get(currentKey).isNull()
&& actualNode.has(currentKey)
&& !actualNode.get(currentKey).isNull()) {
if (expectedNode.get(currentKey).isArray()) {
if (actualNode.get(currentKey).isArray()
&& actualNode.get(currentKey).size() == expectedNode.get(currentKey).size()) {
boolean subNodeComparisonSucceeded = false;
for (final JsonNode expectedSubNode : expectedNode.get(currentKey)) {
for (final JsonNode actualSubNode : actualNode.get(currentKey)) {
subNodeComparisonSucceeded = JsonNodeComparator(expectedSubNode, actualSubNode);
if(subNodeComparisonSucceeded) {
break;
}
}
if(!subNodeComparisonSucceeded) {
return false;
}
}
} else if(expectedNode.get(currentKey).size() > 0) {
return false;
}
} else if(!expectedNode.get(currentKey).equals(actualNode.get(currentKey))) {
return false;
}
}
}
return true;
}
}