1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ぼくのかんがえたさいきょうのequalsメソッド(Java)

Last updated at Posted at 2017-09-26

JUnitでBean同士の比較をしたくて作ってしまいました。

※equalsメソッドをこれで実装すると無限ループになってしまうバグを修正しました。
※throwsすると呼び出し側がメンドクサイので、内部でcatchへ修正しました。

  • java.lang配下のクラスの場合 ⇒ ネイティブのequalsメソッドを呼び出す。equalsメソッド未実装だったらtoString同士を比較
  • java.lang配下じゃない、かつ配列の場合 ⇒ 長さ、各要素のチェック
  • java.lang配下じゃない、かつ配列じゃない場合 ⇒ フィールドの値をチェック
/**
 * 便利なequalsメソッド
 * equalsメソッドが実装されてなくてもOK.スーパークラスのフィールドもチェックするよ.
 * @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);
    }
}

/**
 * スーパークラスも遡って全てのフィールドを取得する
 * @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;
}

↓こうやって呼び出す。

reflectEquals(obj1, obj2)

と力作作った後にこれだけ↓で済むことに気づいた…

Gson gson = new GsonBuilder().setPrettyPrinting().create();
gson.toJson(obj1).equals( gson.toJson(obj2) );
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?