Java hashCode 应该依赖于 final 变量

Java hashCode should relay on final variables

public lass A {
    private String id;
    private String attr1;
    private String attr2;

    @Override
    public boolean equals(Object obj)    {
        if (!(obj instanceof A)) 
            return false;

        A a = (A) obj;

        return new EqualsBuilder()
                .append(id, a.id)
                .append(attr1, a.attr1
                .append(attr2, a.attr2)
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder()
                .append(id)
                .hashCode();
    }
}

在示例 class 中,id 应该是最终的 hashCode() 才能正常工作。
否则对象将在 属性 修改后从集合中消失,导致内存泄漏。

A a = new A();
a.setId("id1");
a.setAttr1("attr1");
a.setAttr2("attr2");

Set set = new HashSet();
set.add(a);

set.contains(a) == true;

a.setId("id2");

set.contains(a) == false;

我错过了什么吗?为什么在 HashCodeBuilder javadoc 中没有说明?
这让我陷入困境,因为我见过很多 hashCode 和 equals 在同一组字段上进行中继的情况。似乎没有人想到属性修改...

    @Override
    public boolean equals(Object obj)    {
        if (!(obj instanceof A)) 
            return false;

        A a = (A) obj;

        return new EqualsBuilder()
                .append(id, a.id)
                .append(attr1, a.attr1
                .append(attr2, a.attr2)
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder()
                .append(id)
                .append(attr1)
                .append(attr2)
                .hashCode();
    }

它记录在 Object.hashCode javaDocs 中:

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

最终使用的字段将满足这一点。如果不可能,那么只要您以后不更改它们的值,您仍然可以在 hashCode 中使用它们。