Как лучше сравнивать перечисляемые типы в Java

Отредактировано

Что лучше использовать для сравнения enum'ов: == или equals()? В статье разбираем интересные аргументы в пользу обоих вариантов.

27К открытий28К показов

Недавно на Stack Overflow я наткнулся на, казалось бы, простой вопрос:

Что лучше использовать для сравнения enum'ов --- == или equals()?

Вы, конечно, можете сходу ответить, что никакой разницы нет, но будете неправы — в ответах к этому вопросу было приведено много интересных аргументов в пользу обоих вариантов. Я решил, что будет интересно перевести этот спор на русский язык.

Они же оба работают, верно?

Да. В документации написано:

«Допустимо использовать оператор == вместо метода equals, если доподлинно известно, что хотя бы один из них ссылается на перечислимый тип» (“It is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant”).

Причина этого очень простая — каждый из объектов enum создаётся только единожды, и поэтому, если вы создадите десять переменных равных SomeEnum.RED, они все будут ссылаться на один и тот же объект (а оператор == как раз это и проверяет).

Какие есть преимущества у оператора ==?

1. Он никогда не выбросит следующее:

			NullPointerException:enum 
Color {BLACK, WHITE }; 
Color nothing = null;if (nothing == Color.BLACK); // Всё отлично 
if (nothing.equals(Color.BLACK)); // выбрасывает NullPointerException
		

2. В одном из ответов приводилась цитата Джошуа Блоха (автор книги «Effective Java», видимо, и цитата оттуда) о том, что этот оператор работает быстрее, и если гарантируется уникальность каждого экземпляра класса, то стоит использовать именно его.

3. Как известно, сравнения через == проверяются на соответствия типов во время компиляции (это хорошо, поскольку поможет вовремя выявить ошибку): 

			enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };
if (Color.BLACK.equals(Chiral.LEFT)); // Компилируется
if (Color.BLACK == Chiral.LEFT); // Не комбинируется, несовместимые типы!
		

4. Этот вариант короче, и сразу понятно, что происходит именно проверка равенства (то есть вариант более читаемый).

Ого, как серьёзно все подошли к вопросу! Ну теперь точно буду использовать оператор равенства.

Не спешите так. Не все единогласно за ==. Вот что пишут сторонники equals():

  • Нет ни единого случая, когда переменная перечисляемого типа должна быть равна null — если вы так описываете какое-то особое состояние, то его можно просто заменить на ещё одно допустимое состояние enum'а. А значит, NPE не надо скрывать, так как это, вероятнее всего, ошибка, и чем раньше о ней станет известно, тем лучше.
  • Аргумент про скорость == весьма сомнителен. Современные компиляторы, скорее всего умеют заменять equals на == самостоятельно. Если это не так (как доказали позже, это действительно не так), то это проблема Java, над которой нужно работать.
  • Какой Java-программист не знает, что делает equals? Такой вариант наоборот более читаем, так как для объектов мы привыкли использовать именно метод equals. Значит, и для enum’ов нужно поступать так же, чтобы не возникало путаницы.
Следите за новыми постами
Следите за новыми постами по любимым темам
27К открытий28К показов