【问题标题】:Lombok hashCode:: 1. Why good? 2. Why no compile error? [closed]Lombok hashCode:: 1. 为什么好? 2. 为什么没有编译错误? [关闭]
【发布时间】:2022-01-23 17:00:55
【问题描述】:

我有以下简单的 Java 代码,

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class Test{
}

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

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;
    }

...

【问题讨论】:

  • 您是否检查过,当您将状态添加到您的类(即字段)时,hashCode 方法会发生什么?
  • 为什么 result=true 会是编译器问题?有一个无意义的变量并不违法。最多是一个警告。至于它为什么这样做——如果你有实际的字段,很可能会使用它,而且他们没有打扰特殊的外壳,将它删除为无字段类。
  • @GabeSechan 因为声明的变量是inttrueboolean,并且在java 中,与C(++) 不同,它们不匹配。我错了吗? (我在发布之前检查了这个,我得到了一个编译错误。)

标签: java lombok intellij-lombok-plugin


【解决方案1】:

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

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

hashCode() 方法应该读作

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

现在问题来了:

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

确实如此。 equals()hashCode() 的合同规定,对于任何两个对象 o1o2,当 o1.equals(o2) 为真时,它也必须是 o1.hashCode() == o2.hashCode()

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

由于您的类没有任何字段,因此 所有 实例都被视为相等,因此必须具有相同的 hashCode。 hashCode 的实际值无关紧要,只要所有实例的值相同即可。


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

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

Lombok 本身包含一个集成的“delombok”功能 (https://projectlombok.org/features/delombok),该功能为您的第一个 Test 类创建以下源代码(使用 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;
    }
}

【讨论】:

  • 你会说反编译器有错误吗?或者,例如,无法检测到何时使用1 以及何时使用true
【解决方案2】:

我认为这是因为您的 Test 类没有任何字段。因此,当使用@EqualsAndHashCode 时,该类的所有实例都将被视为“相等”。因此,delomboked 实现反映了这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    • 2016-01-21
    • 2017-07-07
    • 1970-01-01
    相关资源
    最近更新 更多