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

修改对象中引用类型属性为何会导致该对象哈希码变化?

问题分析:修改关联对象属性后,主对象哈希码为何变化?

根本原因

这是完全符合代码逻辑的现象,问题出在Lombok的@EqualsAndHashCode注解的默认行为上:

  • 你给Person和Address都添加了@EqualsAndHashCode,Lombok会自动生成基于类中所有字段的equals()和hashCode()方法。
  • Person的hashCode()计算逻辑会包含firstName、lastName以及address这三个字段的哈希值。
  • 当你修改Address的cityName时,Address自身的hashCode()会因为依赖cityName字段而改变,进而导致Person的hashCode()重新计算后的值也跟着变化。

等价代码验证

Lombok为Person生成的hashCode()逻辑大致等价于下面的代码:

@Override
public int hashCode() {
    return Objects.hash(firstName, lastName, address);
}

而Address的hashCode()逻辑是:

@Override
public int hashCode() {
    return Objects.hash(streetName, cityName);
}

显然,cityName修改后Address.hashCode()的值改变,代入Person.hashCode()的计算中,最终结果必然发生变化。

关于测试中的浅拷贝

你的测试用了Person.clone(),这是浅拷贝,所以alex和shallowCopyOfAlex指向同一个Address对象。修改alex.getAddress().setCityName()后,两个Person对象的address引用指向的是同一个修改后的Address实例,因此它们的hashCode()会同步变化,这也解释了测试输出里两个Person哈希码前后一致且同时改变的现象。

解决方案:让Person哈希码不依赖Address状态

如果需要Person的哈希码不受Address属性变化的影响,可以修改Person的@EqualsAndHashCode注解,排除address字段:

@Setter
@AllArgsConstructor
@EqualsAndHashCode(exclude = "address") // 排除address字段
public class Person implements Cloneable {
    // ... 原有代码内容
}

这样Person的hashCode()只会基于firstName和lastName计算,修改Address的属性就不会影响Person的哈希码了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:43:46