Reputation: 4830
I need compare all fields of two objects and return number of differences.
Pseudocode looks like below:
public int differentFields(Foo foo1, Foo foo2) {
int differentFields = 0;
for all fields of foo1 and foo2:
if foo1.field[i] != foo2.field[i]
differentFields++;
return differentFields;
}
Fields have the same names because I want to compare objects of the same class.
I cannot do that using standard equals because Foo has a lot of fields and I would have to write too much if statements.
How can I do that using reflection?
Upvotes: 0
Views: 60
Reputation: 1835
As mentioned in the comments, it is a bad idea to use reflection to get all class members. This should solve your requirement:
public <T> int countDiff(T t1, T t2) throws Exception {
int diffCount = 0;
Class<? extends Object> tClass = t1.getClass();
for (Field field : tClass.getDeclaredFields()) {
field.setAccessible(true);
Object value1 = field.get(t1);
Object value2 = field.get(t2);
if (!isEqual(value1, value2)) {
diffCount++;
}
}
return diffCount;
}
private boolean isEqual(Object v1, Object v2) {
return (v1 == null && v2 == null) || (v1 != null && v1.equals(v2));
}
A quiet better solution would be to loop over the getter (but it is still a bad idea:
public <T> int countDiff(T t1, T t2) throws Exception {
int diffCount = 0;
Class<? extends Object> tClass = t1.getClass();
for (Method method : tClass.getMethods()) {
if (!isGetter(method)) {
continue;
}
Object value1 = method.invoke(t1);
Object value2 = method.invoke(t2);
if (!isEqual(value1, value2)) {
diffCount++;
}
}
return diffCount;
}
private boolean isGetter(Method m) {
boolean name = m.getName().startsWith("get") || m.getName().startsWith("is");
return name && m.getParameterTypes().length == 0 && m.getReturnType() != Void.TYPE;
}
private boolean isEqual(Object v1, Object v2) {
return (v1 == null && v2 == null) || (v1 != null && v1.equals(v2));
}
EDIT Thanks @tobias_k: also is
methods for boolean added
Upvotes: 2