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

如何重写含30+属性类的equals方法,避免逐一列举属性?

嘿,我完全懂这种痛苦——30多个属性一个个写Objects.equals(),不仅手酸还容易漏写,后期加属性也容易忘更新equals方法。给你几个实用的解决方案,按推荐程度排序:

1. 用Lombok(最省心的方案)

这绝对是首选,只需要在你的类上加上@EqualsAndHashCode注解,Lombok会在编译时自动帮你生成覆盖所有非静态、非transient属性的equals和hashCode方法,完全不用自己写一行代码。

示例代码:

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class Address {
    private String attr1;
    private int attr2;
    // ... 剩下30多个属性
}

如果需要自定义规则,还可以通过注解参数调整:

  • exclude = {"attrX"}:排除指定属性不参与比较
  • callSuper = true:将父类的字段也纳入比较范围

2. 用Apache Commons Lang的EqualsBuilder

如果你不想引入Lombok,Apache Commons Lang库的EqualsBuilder提供了反射式的比较方法,一行代码就能搞定:

import org.apache.commons.lang3.builder.EqualsBuilder;

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Address address = (Address) o;
    return EqualsBuilder.reflectionEquals(this, address);
}

同样支持自定义排除字段:

// 排除attr3和attr5不参与比较
return EqualsBuilder.reflectionEquals(this, address, "attr3", "attr5");

也可以通过reflectionEquals(this, address, false)来关闭默认的transient字段忽略规则。

3. 手动实现反射遍历(适合不想加依赖的场景)

如果不想引入任何第三方库,也可以自己写反射代码来遍历字段。不过要注意处理字段权限、静态/transient字段过滤,以及异常情况:

import java.lang.reflect.Field;
import java.util.Objects;

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    
    Address other = (Address) o;
    Field[] fields = getClass().getDeclaredFields();
    
    for (Field field : fields) {
        // 跳过静态和transient字段
        if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) || 
            java.lang.reflect.Modifier.isTransient(field.getModifiers())) {
            continue;
        }
        
        try {
            field.setAccessible(true);
            Object thisValue = field.get(this);
            Object otherValue = field.get(other);
            
            if (!Objects.equals(thisValue, otherValue)) {
                return false;
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Failed to compare fields in equals method", e);
        }
    }
    return true;
}

这种方式会自动适配类的字段变化,不用手动更新equals方法,但反射性能略低于手动编写的代码,适合非高频调用的场景。

重要提醒

不管用哪种方案,都要保证hashCode方法和equals方法逻辑一致(比如Lombok会自动生成匹配的hashCode,EqualsBuilder也有reflectionHashCode方法),否则会导致HashMap、HashSet等集合类行为异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:37:12