有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java深层反射比较

我试图通过比较结果对象和原始对象来验证序列化和反序列化例程。这些例程可以序列化任意和深度嵌套的类,因此我想要一个比较例程,它可以提供原始实例和最终实例,反射地遍历每个值类型,比较值,并迭代地深入引用类型以比较值

我尝试过Apache Commons Lang^{},但这似乎并没有进行非常深入的比较,它只是比较引用类型是否相等,而不是深入研究它们:

下面的代码说明了我的问题。对reflectionEquals的第一个调用返回true,但第二个调用返回false

有没有人可以推荐一套图书馆套路

class dummy {
    dummy2 nestedClass;
}

class dummy2 {
    int intVal;
}

@Test
public void testRefEqu() {

    dummy inst1 = new dummy();
    inst1.nestedClass = new dummy2();
    inst1.nestedClass.intVal = 2;
    dummy inst2 = new dummy();
    inst2.nestedClass = new dummy2();
    inst2.nestedClass.intVal = 2;
    boolean isEqual = EqualsBuilder.reflectionEquals(inst1.nestedClass, inst2.nestedClass);
    isEqual = EqualsBuilder.reflectionEquals(inst1, inst2);
}

共 (4) 个答案

  1. # 1 楼答案

    一种方法是使用反射来比较对象,但这很棘手。另一种策略是比较序列化对象的字节数组:

    class dummy implements Serializable {
        dummy2 nestedClass;
    }
    
    class dummy2  implements Serializable {
        int intVal;
    }
    
    @Test
    public void testRefEqu() throws IOException {
    
        dummy inst1 = new dummy();
        inst1.nestedClass = new dummy2();
        inst1.nestedClass.intVal = 2;
    
        dummy inst2 = new dummy();
        inst2.nestedClass = new dummy2();
        inst2.nestedClass.intVal = 2;
    
        boolean isEqual1 = EqualsBuilder.reflectionEquals(inst1.nestedClass, inst2.nestedClass);
        boolean isEqual2 = EqualsBuilder.reflectionEquals(inst1, inst2);
    
        System.out.println(isEqual1);
        System.out. println(isEqual2);
    
        ByteArrayOutputStream baos1 =new ByteArrayOutputStream();
        ObjectOutputStream oos1 = new ObjectOutputStream(baos1);
        oos1.writeObject(inst1);
        oos1.close();
    
        ByteArrayOutputStream baos2 =new ByteArrayOutputStream();
        ObjectOutputStream oos2 = new ObjectOutputStream(baos2);
        oos2.writeObject(inst1);
        oos2.close();
    
        byte[] arr1 = baos1.toByteArray();
        byte[] arr2 = baos2.toByteArray();
    
        boolean isEqual3 = Arrays.equals(arr1, arr2);
    
        System.out.println(isEqual3);
    
    }
    

    应用程序序列化和反序列化对象,因此这种方法似乎是解决问题的最快解决方案(就CPU操作而言)

  2. # 2 楼答案

    从对这个问题的回答和一些初步测试来看,Unitils的ReflectionAssert.assertReflectionEquals似乎达到了您的预期。(编辑:但可能会被放弃,所以您可以尝试AssertJhttps://assertj.github.io/doc/#assertj-core-recursive-comparison

    2021编辑:^ {}现在有一个^ {CD3>}选项。然而,上面提到的单元测试库将为您提供更好的故障消息来帮助调试,因此根据上下文,它们仍然是最佳选择

  3. # 3 楼答案

    在所讨论的类上实现equals()方法。每个调用的equals将比较嵌套类的相等性(或者,如果愿意,将比较数据成员的相等性)。正确编写的equals方法总是会导致深入比较

    在您的示例中,dummy类equals是这样的:

    public boolean equals(Object other)
    {
        if (other == this) return true;
        if (other instanceOf dummy)
        {
            dummy dummyOther = (dummy)other;
            if (nestedClass == dummyOther.nestedClass)
            {
               return true;
            }
            else if (nestedClass != null)
            {
               return nestedClass.equals(dummyOther);
            }
            else // nestedClass == null and dummyOther.nestedClass != null.
            {
               return false;
            }
        }
        else
        {
          return false;
        }
    }
    
  4. # 4 楼答案

    您可以使用AssertJ的field by field recursive comparison功能,例如:

    import static org.assertj.core.api.BDDAssertions.then;
    
    then(actualObject).usingRecursiveComparison().isEqualTo(expectedObject);