比较任意两个Java对象的常见方法

6

我希望能够比较两个Java对象而不需要重写equals方法。由于我需要在多个类中重写equals方法,因此我需要一个通用的实用程序方法,可以比较两个Java对象。

类似于下面这样的东西

A a1,a2;
B b1,b2;
C c1,c2;
-----
-----
boolean isEqual1 = new ObjectComparator().isEquals(a1 , a2);
boolean isEqual2 = new ObjectComparator().isEquals(b1 , b2);
boolean isEqual3 = new ObjectComparator().isEquals(c1 , c2);

请帮我编写一个通用的实用程序,用于比较任何Java对象。
希望通过使用"Field"类和"getClass"方法来实现。请指导我。

看一下这个:http://www.unitils.org/apidocs/org/unitils/reflectionassert/ReflectionComparator.html - amod
7个回答

9
请查看Apache Commons库中的EqualsBuilder.reflectionEquals
根据文档
此方法使用反射来确定两个对象是否相等。它使用AccessibleObject.setAccessible来访问私有字段。这意味着,如果在安全管理器下运行且权限未正确设置,它将引发安全异常。与显式测试相比,它也不太高效。
所以,在您的示例中,它应该是:
A a1,a2;
B b1,b2;
C c1,c2;
-----
-----
boolean isEqual1 = EqualsBuilder.reflectionEquals(a1 , a2);
boolean isEqual2 = EqualsBuilder.reflectionEquals(b1 , b2);
boolean isEqual3 = EqualsBuilder.reflectionEquals(c1 , c2);

非常感谢。那给了我一个起点。我需要自定义该类以添加某些功能,例如将异常添加到比较字段等。通过扩展该类,EqualsBuilder类能帮助我实现这些功能吗? - John Solomon
警告:根据EqualsBuilder.reflectionEquals(Object lhs, Object rhs) Javadoc,“瞬态成员将不会被测试”。因此,例如EqualsBuilder.reflectionEquals(new Date(2), new Date(3))将返回true。最好使用reflectionEquals(Object lhs, Object rhs, boolean testTransients)。 - machinery

4

[...]不覆盖equals方法[...] (+1 无论如何;-) - aioobe
这是一个来自文档的示例,你可以直接调用而无需覆盖它。 ;) - Peter Lawrey
1
警告:根据EqualsBuilder.reflectionEquals(Object lhs, Object rhs) Javadoc,“瞬态成员将不会被测试”。因此,例如EqualsBuilder.reflectionEquals(new Date(2), new Date(3))将返回true。最好使用reflectionEquals(Object lhs, Object rhs, boolean testTransients)。 - machinery

2

1
警告:根据EqualsBuilder.reflectionEquals(Object lhs, Object rhs) Javadoc,“瞬态成员将不会被测试”。因此,例如EqualsBuilder.reflectionEquals(new Date(2), new Date(3))将返回true。最好使用reflectionEquals(Object lhs, Object rhs, boolean testTransients)。 - machinery

1

首先,您是否有充分的理由不想使用equals方法?equals方法在集合类等内部使用,因此您必须遵守equals协议。

如果有理由,则可以使用反射逐个字段进行比较。 获取类的字段列表,并对每个字段检查值。您还需要确保它们都是同一类的实例。


1
有一个令人信服的理由,那就是我的类可能会随着更多字段的增加而增长。每一次我都需要更新 equals 方法。 - John Solomon

0

你可能想考虑使用Shazamcrest

从他们的Github页面:

Having a Person bean with the following structure:

Person person
    |-- String name
    |-- String surname
    |-- Address address
        |-- String streetName
        |-- int streetNumber
        |-- String postcode

to compare two Person beans with Shazamcrest we would write:

assertThat(actualPerson, sameBeanAs(expectedPerson));

0

试试这个。如果你要比较的对象很大,这个方法可以完美地工作,但需要更多的堆空间。 org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals(obj1, obj2)

http://www.unitils.org/

您可以从下面获取jar文件。

<!-- https://mvnrepository.com/artifact/org.unitils/unitils -->
      <dependency>
          <groupId>org.unitils</groupId>
          <artifactId>unitils</artifactId>
          <version>2.2</version>
      </dependency>

0

您希望在Java 1.7中的java.util包中使用Objects.equals(a,b)

如果您使用的是早于Java 1.7的版本,您可以使用其他人建议的库之一,最著名的是Apache Commons项目。


3
你的意思是这里用到了Objects.deepEquals(a, b)。而Objects.equals(a, b)只是使用对象的默认equals()实现,但可以处理null值。 - Asturio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接