Lombok hashCode:: 1. 为什么好? 2. 为什么没有编译错误?

Lombok hashCode:: 1. Why good? 2. Why no compile error?

我有以下简单的 Java 代码,

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class Test{
}

当我查看生成的 delmboked 代码时,我看到以下内容:

public class Test {
    public Test() {
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Test)) {
            return false;
        } else {
            Test other = (Test)o;
            return other.canEqual(this);
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof Test;
    }

    public int hashCode() {
        int result = true;
        return 1;
    }
}

我不明白 hashCode() 的实现。这是一种好的哈希方法吗?为什么 int result = true; 没有编译问题?

我怀疑这与 hashCode()native 有关,但我不明白为什么我会看到这个实现。


更新: 我的主要问题是关于缺少编译错误。例如,如果我添加两个字段,我将有:

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class Test{
    private String name;
    public int age;
}

...

public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + this.age;
        Object $name = this.name;
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

...

我认为这是因为您的 Test class 没有任何字段。因此,在使用 @EqualsAndHashCode 时,class 的所有实例都将被视为“相等”。所以 delmboked 实施反映了这一点。

您看到这样的 hashCode() 方法可能是您用来分析生成的字节码的工具的产物。

在内部,布尔值 truefalse 分别由值 1 和 0 表示。一些字节码反编译器盲目地将 0 翻译成 false 并将 1 翻译成 true - 这似乎是你的情况。

hashCode() 方法应读作

public int hashCode() {
    int result = 1;
    return 1;
}

现在回答问题:

这是一个有效的 hashCode 实现吗?

当然是。 equals()hashCode() 的契约声明对于任何两个对象 o1o2o1.equals(o2) 为真时它也必须是 o1.hashCode() == o2.hashCode() .

Lomboks @EqualsAndHashCode 注释生成代码,使具有相同字段值的两个对象被视为相等(因此必须具有相同的 hashCode)。

由于您的 class 没有任何字段,所有 实例被认为是相等的,因此必须具有相同的 hashCode。 hashCode 的实际值并不重要,只要它对所有实例都是相同的值即可。


您在反编译器中看到的代码是否有错误?

是的,显然是(因为反编译器生成了无效的源代码)。

Lombok 本身包含一个集成的“delombok”功能 (https://projectlombok.org/features/delombok),该功能会为您的第一个测试创建 class 以下源代码(使用 Lombok 1.18.22):

public class Test {
    @Override
    public boolean equals(final Object o) {
        if (o == this) return true;
        if (!(o instanceof Test)) return false;
        final Test other = (Test) o;
        if (!other.canEqual((Object) this)) return false;
        return true;
    }

    protected boolean canEqual(final Object other) {
        return other instanceof Test;
    }

    @Override
    public int hashCode() {
        final int result = 1;
        return result;
    }
}