Почему сравнение перечислений с использованием == вызывает предупреждение PMD?

Ниже сравниваются два значения перечисления с использованием ==:

MyEnum enum1 = blah();     // could return null
MyEnum enum2 = blahblah()  // could return null
if (enum1 == enum2) {
    // ...
}

Но PMD выдает предупреждение CompareObjectsWithEquals в строке 3:

Используйте equals() для сравнения ссылок на объекты

Не уверен, что понимаю исходный код для этой проверки, но подумал, что можно сравнить два перечисления с использованием ==, поэтому мне интересно, можно ли улучшить мой код или проверка неверна.


person Steve Chambers    schedule 18.06.2015    source источник
comment
Все хорошо. Может быть актуально: sourceforge.net/p/pmd/bugs/1028   -  person MadConan    schedule 18.06.2015
comment
См. также Сравнение членов перечисления Java: == или equals()?.   -  person Raedwald    schedule 13.09.2019


Ответы (2)


Это действительно считается ошибкой:

Однако кажется сложным поймать все возможные случаи (цитата из более новой ошибки):

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

Мне удалось настроить правило, чтобы проверить, является ли тип переменных Enum. Это работает только в том случае, если типы Enum находятся в «auxclasspath» pmd, чтобы разрешение типа могло его найти.

Ваш изолированный пример все равно вызовет это ложное срабатывание, поскольку PMD не знает, что такое ProcessingStatus. Я проверил это с помощью java.math.RoundingMode, который всегда находится в пути к классам и будет разрешен.

(«Ваш пример» относится к автору тикета, а не к OP в Stack Overflow)

Ваш случай может работать с PMD 5, источник, на который вы ссылаетесь, принадлежит PMD 4.

Обновление: текущий источник содержит дополнительную проверку перечислений:

 // skip, if it is an enum
 if (type0.getType() != null && type0.getType().equals(type1.getType()) && type0.getType().isEnum()) {
      return data;
 }
person Marvin    schedule 18.06.2015

Можно использовать .equals(), потому что внутри экземпляры сравниваются с ==.

public final boolean equals(Object other) {
    return this==other;
}

Обратите внимание, что эта реализация .equals() является final, что означает, что вы не можете переопределить ее в своем перечислении.

person Konstantin Yovkov    schedule 18.06.2015
comment
Спасибо, но любое из перечислений может быть нулевым, поэтому не хочу рисковать NullPointerException. - person Steve Chambers; 18.06.2015
comment
Тогда вам придется добавить чек. Или используйте тип Optional<T> Java8. :) - person Konstantin Yovkov; 18.06.2015
comment
Или придерживайтесь enum1 == enum2 и игнорируйте это предупреждение PMD. - person stuXnet; 18.06.2015