I'm thinking about to create a reflective helper method for equals and hashCode.
- In case of equals the helper method looks over the reflection API to the fields of objectA and compares them with fields of objectB.
- In case of hashCode the helper method looks over the reflection API to the fields and calculates a hashCode in a iteration loop.
The good thing is that I don't to be worry about missing fields in my equals or hashCode implementation. The bad thing is I guess performance. What do you think about this idea? Please share your opinion!
This is my first draft for equals:
public final class ReflectiveEqualsHelper {
public static boolean isEqual(final Object a, final Object b) {
    if (!isTypeEqual(a, b)) {
        return false;
    }
    Field[] fields = getFields(a);
    Object valueA;
    Object valueB;
    String fieldName;
    for (int i = 0; i < fields.length; i++) {
        fieldName = fields[i].getName();
        valueA = getValueByFieldName(a, fieldName);
        valueB = getValueByFieldName(b, fieldName);
        if (!compare(valueA, valueB)) {
            return false;
        }
    }
    return true;
}
@SuppressWarnings("rawtypes")
private static Field[] getFields(final Object o) {
    Class clazz = o.getClass();
    Field[] fields = clazz.getDeclaredFields();
    return fields;
}
private static Field getField(final Object o, final String name) {
    try {
        Field field = o.getClass().getDeclaredField(name);
        return field;
    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    }
}
private static Object getValueByFieldName(final Object o, final String name) {
    Field field = getField(o, name);
    field.setAccessible(true);
    try {
        Object value = field.get(o);
        field.setAccessible(false);
        return value;
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}
private static boolean areBothNull(final Object a, final Object b) {
    return (a == null && b == null);
}
private static boolean isTypeEqual(final Object a, final Object b) {
    if (areBothNull(a, b)) {
        return false;
    }
    return a.getClass().equals(b.getClass());
}
private static boolean compare(final Object a, final Object b) {
    if (a == null) {
        return false;
    } else if (b == null) {
        return false;
    }
    return a.equals(b);
}
}
public class ReflectiveEqualsHelperTest {
@Test
public void testIsEqual() {
    Vector a = new Vector(Long.valueOf(1L), 3L);
    Vector b = new Vector(Long.valueOf(1L), 3L);
    Vector c = new Vector(Long.valueOf(2L), 3L);
    boolean testA = ReflectiveEqualsHelper.isEqual(a, b);
    boolean testB = ReflectiveEqualsHelper.isEqual(a, c);
    boolean testC = ReflectiveEqualsHelper.isEqual(b, c);
    assertTrue(testA);
    assertFalse(testB);
    assertFalse(testC);
}
class Vector {
    public static final int STATIC = 1;
    private Long x;
    private long y;
    public Vector(Long x, long y) {
        super();
        this.x = x;
        this.y = y;
    }
    public Long getX() {
        return x;
    }
    public void setX(Long x) {
        this.x = x;
    }
    public long getY() {
        return y;
    }
    public void setY(long y) {
        this.y = y;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((x == null) ? 0 : x.hashCode());
        result = prime * result + (int) (y ^ (y >>> 32));
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        return ReflectiveEqualsHelper.isEqual(this, obj);
    }
}
}
Cheers, Kevin
 
     
     
     
    
