Lombok EqualsAndHashCode 是否检查 Class 类型

Does Lombok EqualsAndHashCode Check Class Type

Lombok @EqualsAndHashCode 是否检查 class type/instance?

编辑:我想提一下,我在一家拥有自己框架的大公司工作,就像许多其他公司一样,我们受到限制。由于我们的安全需要多么密集(你们中的许多人在你们所​​在的州没有电),我无法在我们的框架之外添加图书馆。所以 Lombok 最近才被引入我们的框架(版本 1.18.12,直到 2 月 20 日才发布)Java 8 给你另一个我正在使用的例子和 code/libraries 我可能已经接触到了。因此,如果我对 Lombok 不是很精通,或者在评论中提到它之前我从未听说过 Delombok,请原谅我。

回到问题:

我读过 https://projectlombok.org/features/EqualsAndHashCode 几遍,但我不断得出不同的结论。

下面是我正在做的一个例子来帮助澄清我的问题:

@Entity
@Table(name = GeneratorTypeA.VIEW)
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
public class GeneratorTypeA extends AbstractGenerator {
    ...
    @Id
    @EqualsAndHashCode.Include
    @SequenceGenerator(...)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GeneratorA.seq.id")
    @Column(name = "GENERATOR_A_ID", precision = 19, scale = 0)
    private Long id;
    ...
}

GeneratorTypeB 看起来与上面的代码片段完全一样。现在说我有以下内容:

final Set<GeneratorTypeA> generatorsA = ...;
final Set<GeneratorTypeB> generatorsB = ...;

每个实体仅在“id”参数上使用@EqualsAndHashCode.Include。我正在使用下面的代码将 Set 和 Set 组合成一个 Set。因为我只是明确地写了唯一的 id 应该用于相等,所以当我组合它们时我可能会丢失两个集合中的实体,除非 Lombok 也比较每个对象的“实例”。那么有谁知道 Lombok 是否执行此检查(将 onlyExplicitlyIncluded 设置为 true - 或一般情况下)或者是否有一种方法可以通过添加此检查来利用 Lombok?

我想在没有 Lombok 的情况下使用等效的 equals 方法:

public boolean equals(final Object other) {
    if (!(other instanceof GeneratorTypeA)) {
        return false;
    }
    final GeneratorTypeA castOther = (GeneratorTypeA) other;
    return new EqualsBuilder().append(getId(), castOther.getId()).isEquals();
}

我用来组合集合的代码在此设置下运行良好,但我正在处理大量数据,因此 运行 进入 equals 方法中使用的重复唯一标识符的机会是非常低,但它为意外打开了大门 functionality/bugs。

public static <T> Set<?> combine(final Set<?>... sets) {
    return Stream.of(sets).flatMap(Set::stream).collect(Collectors.toSet());
}

Lombok,可以很好地生成 equals 和 hashcode,您不必为此担心。但是,当您 覆盖 equals 和 hashcode 并在 Hash 类型集合 中使用这些对象时,您应该小心并且(了解这一点很重要)对象不是不可变的。那么你可能会有意想不到的结果。让我用一个具体的例子来告诉你:

public class SetTest  {

    @Getter
    @Setter
    @AllArgsConstructor
    @EqualsAndHashCode
    @ToString
    static class User {
        private String name;
        private int age;
    }

    public static void main(String[] args) {
        Set<User> users = new HashSet<>();
        User user1 = new User("Jane", 25);
        User user2 = new User("John", 40);
        users.add(user1);
        users.add(user2);

        user1.setAge(26);
        users.add(user1);

        System.out.println(users);
    }
}

答案:[Task.SetTest.User(name=Jane, age=26), Task.SetTest.User(name=Jane, age=26), Task.SetTest.User(name=John, age=40)]

如您所见,现在集合中有 3 个对象,而不是 2 个。发生这种情况是因为从 HashSet 以这种方式执行添加:

  1. 添加新对象时,会计算哈希码
  2. 哈希码,标识所有具有相同哈希码的对象(冲突对象)所在的桶
  3. 对该桶(如果存在)中的所有对象进行循环,并将对象与等值进行比较
  4. 如果新添加的对象与桶中的对象之一匹配,则该对象不添加到集合中,否则添加

在我的例子中,在我更改用户 Jane 的年龄后,我更改了 hashcode 的值,并且该对象被添加到集合中,因为集合中不存在具有相同 hashcode 的其他对象。

是;该对象必须是 this class.

的实例

根据 documentation:

if (!(o instanceof EqualsAndHashCodeExample)) return false;

顺便说一句,具有讽刺意味的是,您的公司显然如此注重安全,以至于选择等待多年才采用 java 1.8,但等待的时间太长以至于 1.8 已经停产 在您采用它之前并且支持已经终止,使您暴露在未修补的安全漏洞之下。