利用反射比较两个对象是否相等

java开发中,Junit做单测是必不可少的一环。然而对于单测结果的比较,仅仅通过Assert断言来比较远远不够。Assert只能比较基本类型,而对于对象是否相等,只能取出对象的值来,一一断言对比。这无疑给开发增加了很多无用的工作。下面简单介绍一个利用反射机制来实现对象比较的例子。话不多说,上代码。

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);
    }
}

在这段代码里面,我创建了一个测试用的实体类,其中包含一个字符串属性,一个整型属性,一个Map属性以及一个实体类属性。通过上面代码可以看到,两个测试用的实体类的属性是一样的,然而使用断言,抛出了断言失败的异常。

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)

接下来使用反射机制来实现对象的比较。上代码:

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

        // 记录比较结果
        boolean retFlag = true;

        // 首先判断需要比较的对象是否为null,一个为null,一个不是null时,返回不相等
        if((o1 == null && o2 != null)||(o1 != null && o2 == null)){
            return false;
        }

        // 都为null时,返回相等
        if(o1 ==null && o2==null){
            return true;
        }

        // +++++++++++++++++++++++都不为null时,继续比较+++++++++++++++++++++++++++++++

        // 首先比较两个对象的类型是否一致,类型不一致,直接返回不相等
        if(o1.getClass().isInstance(o2)){


            try {

                // 通过反射获取到需要比较的对象类
                Class clzz = Class.forName(o1.getClass().getName());

                // 获取类对应的属性对象
                Field[] fs = clzz.getDeclaredFields();

                // 依次比较各属性值
                for(Field ftemp : fs){

                    // 获取属性名称
                    String fieldName = ftemp.getName();

                    // 组装属性对应的get方法
                    String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);

                    // 通过get方法获取属性值
                    Object v1 = clzz.getMethod(methodName).invoke(o1);
                    Object v2 = clzz.getMethod(methodName).invoke(o2);

                    // +++++++++++++++++++此处使用枚举出类型的方式,方法欠佳,仅供参考。+++++++++++++++++
                    // 如果是基本类型或者是集合类型,则直接调用对象的equals方法
                    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(!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;
    }

    /**
     * 如果是基本类型或集合类,则直接用equals方法比较
     *
     * @param o1
     * @param o2
     * @return
     */
    private static boolean compareValue(Object o1, Object o2){

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

        // 集合类特性,实现了equals比较
        if(o1.equals(o2)){
            return true;
        }

        return false;
    }

下面是执行结果:
在这里插入图片描述
欢迎提问并指出更优方案。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值