You can use reflection as workaround for your problem, but the best way to do it will be as @imperezivan said, using a common ancestor to have the attributes in the same place.
A reflection implementation will be as easy as getting all the fields of each object, and compare its values. Here you have an example:
public static boolean compareObjects(Object o1, Object o2) {
try {
List<Field> fields1 = getFields(o1);
List<Field> fields2 = getFields(o2);
boolean found;
Field field2Temp = null;
for (Field field1 : fields1) {
found = false;
for (Field field2 : fields2) {
if (field1.getName().equals(field2.getName())) {
if (!field1.get(o1).equals(field2.get(o2))) {
System.out.println("Value " + field1.get(o1) + " for field " + field1 + " does not match the value " + field2.get(o2) + " for field " + field2);
return false;
}
field2Temp = field2;
found = true;
}
}
if (!found) {
System.out.println("Field " + field1 + " has not been found in the object " + o2.getClass());
return false;
} else {
fields2.remove(field2Temp);
}
}
if (fields2.size() > 0) {
for (Field field : fields2) {
System.out.println("Field " + field + " has not been found in the object " + o1.getClass());
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private static List<Field> getFields(Object o) {
Field[] fields = o.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
}
return new ArrayList<>(Arrays.asList(fields));
}
As you can see I'm forcing the fields to match, so if one field is not found in the other object, the method will return false, but you can easily change it depending on your needs.
This code gives some details about where the problem is if two objects are different.
With this execution:
public static void main(String args[]){
Bean1 bean1 = new Bean1(1);
Bean2 bean2 = new Bean2(1);
System.out.println("Equals? " + bean1.equals(bean2));
System.out.println("Reflection equals? " + compareObjects(bean1, bean2));
bean2 = new Bean2(2);
System.out.println("Equals? " + bean1.equals(bean2));
System.out.println("Reflection equals? " + compareObjects(bean1, bean2));
}
The results you get are:
Equals? false
Reflection equals? true
Equals? false
Value 1 for field private int com.test.so.Bean1.id does not match the value 2 for field private int com.test.so.Bean2.id
Reflection equals? false
If you plan to use this code, please test the edge cases as I haven't done it