Lombok: Проблема с hashCode() для нулевого атрибута при использовании структуры на основе хэша

Созданный на 19 июл. 2019  ·  3Комментарии  ·  Источник: projectlombok/lombok

Аннотация @EqualsAndHashCode , использующая атрибут Long, такой как pk , может привести к непредвиденному поведению при использовании со структурой на основе хеша (например, HashSet).

например.:

<strong i="9">@Entity</strong>
@EqualsAndHashCode(of = "pk")
class Foo {

    <strong i="10">@Id</strong>
    private Long pk;

    private LocalDate createdAt;

}
<strong i="13">@Entity</strong>
class Foo {

    <strong i="14">@Id</strong>
    private Long pk;

    private LocalDate createdAt;

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

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
}

Поэтому, когда экземпляр с pk = null и другой с pk = 43, он вернет один и тот же хэш-код, и его можно будет считать одинаковым в структуре на основе хэша, а это не так.

И в случае использования OmniFaces ListConverter, который использует toString , у нас возникает та же проблема.

Возможно, вернуть хэш-код экземпляра объекта, а не жестко заданную константу

Вы уже использовали этот сценарий или знаете какой-то способ обойти эту ситуацию?!

Информация о версии

  • Ломбок => 1.18.8
  • Платформа => Windows 10 JDK 11.0.4 IntelliJ

Самый полезный комментарий

43, вероятно, так же хорошо, как и любое другое число, и лучше, чем -1, 0 и 1. Если сделать его настраиваемым, это увеличит нагрузку на техническое обслуживание при очень низкой добавленной стоимости.

Использование хэш-кода Identity для null нарушит контракт equals.

Все 3 Комментарий

Поэтому, когда экземпляр с pk = null и другой с pk = 43, он вернет тот же хэш-код.

Это не имеет значения. Более того, всегда будут коллизии хешей, независимо от того, что вы выберете.

Обратите внимание, что Arrays.hashCode , String.hashCode и многие другие производят множество столкновений, что совершенно бессмысленно.

Возможно, вернуть хэш-код экземпляра объекта, а не жестко заданную константу

В моем коде, написанном вручную, я утверждаю, что он не вызывается до того, как будет назначено значение id . Это, конечно, странно, но таковы все альтернативы.

В этом случае можно было бы создать параметр аннотации, который мог бы указать, какое значение следует использовать, когда ПК имеет значение null. По умолчанию 43.

Это дало бы больше контроля разработчику.

@EqualsAndHashCode(of = "pk", ifAnyNull = -1)

Таким образом, он будет использовать -1 вместо 43 для любого поля, которое было нулевым.

43, вероятно, так же хорошо, как и любое другое число, и лучше, чем -1, 0 и 1. Если сделать его настраиваемым, это увеличит нагрузку на техническое обслуживание при очень низкой добавленной стоимости.

Использование хэш-кода Identity для null нарушит контракт equals.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги