I made it because I wanted to compare beans with JUnit.
Fixed a bug that an infinite loop occurs when the equals method is implemented with this.
When throws, the caller is Mendokusai, so I modified it to catch internally.
For classes under java.lang ⇒ Call the native equals method. Compare toStrings if equals method is not implemented
If it is not under java.lang and it is an array ⇒ Check the length and each element
If it is not under java.lang and it is not an array ⇒ Check the value of the field
/**
*Convenient equals method
*OK even if the equals method is not implemented.I'll also check the superclass fields.
* @param a
* @param b
* @return
*/
@SuppressWarnings("unchecked")
public static boolean reflectEquals( Object a, Object b ){
try{
if (a == b) {
return true;
}
if (a == null || b == null ) {
return a == b;
}
if (a.getClass() != b.getClass()) {
return false;
}
boolean useBuildinEqualsFlg = a.getClass().getName().startsWith("java.lang");
if( useBuildinEqualsFlg ){
try{
Method equalsMethod = a.getClass().getDeclaredMethod("equals", Object.class);
boolean eqFlg = Boolean.class.cast( equalsMethod.invoke(a, b) );
return eqFlg;
}catch( NoSuchMethodException e ) {
String aStr = a.toString();
String bStr = b.toString();
boolean eqFlg = aStr.equals(bStr);
return eqFlg;
}
}else{
if( a instanceof List ) {
a = ((List<Object>) a).toArray();
b = ((List<Object>) b).toArray();
}
if( a.getClass().isArray() ) {
int aLen = Array.getLength(a);
int bLen = Array.getLength(b);
if( aLen != bLen ) {
return false;
}
for( int i = 0;i<aLen;i++) {
Object aElement= Array.get(a, i);
Object bElement= Array.get(b, i);
if( !reflectEquals( aElement, bElement ) ) {
return false;
}
}
return true;
}
List<Field> fields = getAllFields(a.getClass());
for( Field field : fields ) {
field.setAccessible(true);
Object aFieldObj = field.get(a);
Object bFieldObj = field.get(b);
boolean eqFlg = reflectEquals( aFieldObj, bFieldObj);
if( !eqFlg ) {
return false;
}
}
return true;
}
}catch(IllegalAccessException | IllegalArgumentException | SecurityException | InvocationTargetException e ){
throw new RuntimeException(e);
}
}
/**
*Superclass also goes back and gets all fields
* @param clazz
* @return
*/
private static List<Field> getAllFields(Class<?> clazz){
List<Field> allFields = new ArrayList<>();
if( clazz != Object.class ) {
Field[] fields = clazz.getDeclaredFields();
allFields.addAll( Arrays.asList(fields) );
allFields.addAll( getAllFields(clazz.getSuperclass()) );
}
return allFields;
}
↓ Call like this.
reflectEquals(obj1, obj2)
After making a masterpiece, I realized that this is all I need to do ...
Gson gson = new GsonBuilder().setPrettyPrinting().create();
gson.toJson(obj1).equals( gson.toJson(obj2) );
Recommended Posts