Comparing two objects by reflection

Keywords: Java Attribute Junit

In the development of java, Junit is an indispensable link to do single test. However, for the comparison of single measurement results, it is far from enough to use Assert assertion alone. Assert can only compare basic types, and for the equality of objects, only the value of the object can be taken out, one by one assertion comparison. This undoubtedly adds a lot of useless work to development. Here is a brief introduction to an example of using reflection mechanism to achieve object comparison. Don't say much. Code it.

public class ReflectTest {


    public static void main(String[] args) {

        Map<String, Object> m = new HashMap();
        m.put("test","testvalue");
        TestEntity next1 = new TestEntity("testStr",222,m);
        TestEntity tn1 = new TestEntity("1212",999,m);
        tn1.setNext(next1);
        TestEntity next2 = new TestEntity("testStr",222,m);
        TestEntity tn2 = new TestEntity("1212",999,m);
        tn2.setNext(next2);

        Assert.assertEquals(tn1, tn2);
    }
}

In this code, I create an entity class for testing, which contains a string attribute, an integer attribute, a Map attribute and an entity class attribute. As you can see from the above code, the attributes of the two entity classes used for testing are the same, but the exception that the assertion failed is thrown using the assertion.

Exception in thread "main" java.lang.AssertionError: expected [com.mytest.Reflect.TestEntity@4b1210ee] but found [com.mytest.Reflect.TestEntity@4d7e1886]
	at org.testng.Assert.fail(Assert.java:94)
	at org.testng.Assert.failNotEquals(Assert.java:494)
	at org.testng.Assert.assertEquals(Assert.java:123)
	at org.testng.Assert.assertEquals(Assert.java:165)
	at com.mytest.Reflect.ReflectTest.main(ReflectTest.java:31)

Next, we use reflection mechanism to achieve object comparison. Upper Code:

private static boolean compareObject(Object o1, Object o2){

        // Record comparison results
        boolean retFlag = true;

        // First of all, it is judged whether the object to be compared is null, one is null, and the other is not null, and the return is not equal.
        if((o1 == null && o2 != null)||(o1 != null && o2 == null)){
            return false;
        }

        // When both are null, return equal
        if(o1 ==null && o2==null){
            return true;
        }

        // +++++++++++++++++++++ Continue to compare +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        // First, we compare whether the two objects have the same type, different type and different direct return.
        if(o1.getClass().isInstance(o2)){


            try {

                // Obtain object classes that need to be compared by reflection
                Class clzz = Class.forName(o1.getClass().getName());

                // Get the attribute object corresponding to the class
                Field[] fs = clzz.getDeclaredFields();

                // Compare attribute values in turn
                for(Field ftemp : fs){

                    // Get the property name
                    String fieldName = ftemp.getName();

                    // get method for assembling attributes
                    String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);

                    // Getting attribute values by get method
                    Object v1 = clzz.getMethod(methodName).invoke(o1);
                    Object v2 = clzz.getMethod(methodName).invoke(o2);

                    // +++++++++++++++++ ++ Enumeration of types is used here, which is not good enough for reference only. +++++++++++++++ ++.
                    // If it is a primitive type or a collection type, the equals method of the object is called directly.
                    if(v1 instanceof String || v1 instanceof Integer || v1 instanceof Short || v1 instanceof Long
                            || v1 instanceof Byte || v1 instanceof Character || v1 instanceof Boolean
                            || v1 instanceof Float || v1 instanceof Double || v1 instanceof Map){

                        if(!compareValue(v1, v2)){
                            retFlag = false;
                            break;
                        }
                    }else{

                        // If it is an object type, continue to recursively call this method
                        if(!compareObject(v1, v2)){
                            retFlag = false;
                            break;
                        }

                    }


                }

            } catch (ClassNotFoundException e) {
                System.out.println("fail to compare Objects !");
                retFlag = false;
            } catch (IllegalAccessException e) {
                System.out.println("fail to compare Objects !");
                retFlag = false;
            } catch (InvocationTargetException e) {
                System.out.println("fail to compare Objects !");
                retFlag = false;
            } catch (NoSuchMethodException e) {
                System.out.println("fail to compare Objects !");
                retFlag = false;
            }
        }else{
            retFlag = false;
        }

        return retFlag;
    }

    /**
     * If it is a primitive type or a collection class, then compare it directly with the equals method
     *
     * @param o1
     * @param o2
     * @return
     */
    private static boolean compareValue(Object o1, Object o2){

        if(o1 ==null || o2==null){
            return false;
        }

        // Collection class features, equals comparison
        if(o1.equals(o2)){
            return true;
        }

        return false;
    }

The following are the results of implementation:

Welcome to ask questions and point out better solutions.

Posted by jonahpup on Sat, 05 Oct 2019 16:57:14 -0700