You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache EqualsBuilder.reflectionEquals判定父子类相等是否符合equals规范?

Is Apache Commons EqualsBuilder.reflectionEquals() Treating Parent/Child Objects as Equal Correct for equals()?

Short answer: Absolutely not — this violates the core contracts of Java's equals() method, making it incorrect behavior for a proper equals() implementation.

Let’s break this down using your examples and Java’s official equals() conventions:

First, the Java equals() Contract Rules Matter

From the Object class specification, two critical rules are being broken here:

  1. Symmetry: If a.equals(b) returns true, then b.equals(a) must also return true. In your test, A().equals(B()) might be true via EqualsBuilder, but B().equals(A()) would almost certainly return false (especially if B has its own equals() implementation or uses IDE-generated logic). This breaks symmetry entirely.
  2. Consistency with class identity: For most non-extensible classes (the vast majority of cases), equals() should only return true if both objects are instances of the exact same class. Using getClass() != o.getClass() (like IDEA's generated code does) enforces this, which prevents the parent/child equality mismatch you’re seeing.

Why Does EqualsBuilder.reflectionEquals() Do This?

Apache Commons' EqualsBuilder is designed for convenient property-by-property comparison via reflection, not strictly adhering to the equals() contract by default. The default reflectionEquals() method only checks the values of shared accessible properties between the two objects — it doesn’t verify that the objects are of the same class.

Even when you use the overload reflectionEquals(new A(), new B(), false, B.class), the excludeClass parameter just stops the comparison at the specified superclass (instead of going all the way to Object), it still doesn’t add a strict class equality check.

IDE-Generated equals() Is Correct for Most Cases

The code IDEA generates follows standard best practices:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    A a = (A) o;
    return x == a.x;
}

By checking getClass() != o.getClass(), it ensures that only instances of the exact same class can be equal. This avoids the symmetry problem and aligns with how most developers expect equals() to behave.

How to Fix EqualsBuilder to Follow the Contract

If you want to use EqualsBuilder for convenience but still comply with equals() rules, add an explicit class check first:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    MyClass that = (MyClass) o;
    return new EqualsBuilder()
            .append(this.x, that.x)
            // Add other properties here
            .isEquals();
}

This way you get the simplicity of EqualsBuilder without violating the equals() contract.

内容的提问来源于stack exchange,提问作者cahen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:21:24