Java enum - зачем использовать toString вместо имени
Если вы посмотрите в enum api по методу name()
, он говорит, что:
Возвращает имя этой константы перечисления, точно так же, как указано в объявлении перечисления. Большинство программистов должны использовать метод toString, предпочитая это, поскольку метод toString может возвращать более удобное имя. Этот метод предназначен в первую очередь для использования в специализированных ситуациях, где правильность зависит от получения точного имени, которое не будет отличаться от выпуска к выпуску.
Почему лучше использовать toString()
? Я хочу сказать, что toString может быть переопределено, когда name() уже является окончательным. Поэтому, если вы используете toString, а кто-то переопределяет его, чтобы вернуть твердое значение, все ваше приложение не работает... Также, если вы посмотрите в источниках, метод toString() возвращает точно и просто имя. Это то же самое.
Ответы
Ответ 1
Это действительно зависит от того, что вы хотите сделать с возвращаемым значением:
- Если вам нужно получить точное имя, используемое для объявления константы перечисления, вы должны использовать
name()
, поскольку toString
может быть переопределен
- Если вы хотите напечатать константу перечисления дружественным образом, вы должны использовать
toString
, который, возможно, был переопределен (или нет!).
Когда я чувствую, что это может запутать, я предоставляю более конкретный метод getXXX
, например:
public enum Fields {
LAST_NAME("Last Name"), FIRST_NAME("First Name");
private final String fieldDescription;
private Fields(String value) {
fieldDescription = value;
}
public String getFieldDescription() {
return fieldDescription;
}
}
Ответ 2
Используйте name()
, если вы хотите сделать сравнение или использовать жестко заданное значение для некоторого внутреннего использования в вашем коде.
Используйте toString()
, когда вы хотите предоставить информацию пользователю (в том числе разработчику, просматривающему журнал). Никогда не полагайтесь на свой код на toString()
, задавая определенное значение. Никогда не проверяйте его на определенную строку. Если ваш код ломается, когда кто-то правильно изменяет возврат toString()
, то он уже был сломан.
Из javadoc (акцент мой):
Возвращает строковое представление объекта. В целом, Метод toString возвращает строку, в которой "текстовое обозначение" объект. Результат должен быть кратким, но информативным представлением это легко для человека для чтения. Рекомендуется, чтобы все подклассы переопределяют этот метод.
Ответ 3
name()
является "встроенным" методом enum
. Это окончательно, и вы не можете изменить его реализацию. Он возвращает имя константы перечисления, как она написана, например. в верхнем регистре, без пробелов и т.д.
Сравните MOBILE_PHONE_NUMBER
и Mobile phone number
. Какая версия более читаема? Я верю, второй. В этом разница: name()
всегда возвращает MOBILE_PHONE_NUMBER
, toString()
может быть переопределен для возврата Mobile phone number
.
Ответ 4
В то время как большинство людей слепо следуют советам javadoc, есть очень конкретные ситуации, когда вы хотите фактически избежать toString(). Например, я использую перечисления в своем Java-коде, но они должны быть сериализованы в базу данных и обратно. Если бы я использовал toString(), то я бы технически был подвержен переопределенному поведению, как указывали другие.
Кроме того, можно также дезацинировать из базы данных, например, это должно всегда работать в Java:
MyEnum taco = MyEnum.valueOf(MyEnum.TACO.name());
В то время как это не гарантируется:
MyEnum taco = MyEnum.valueOf(MyEnum.TACO.toString());
Кстати, я считаю, что Javadoc явно говорит, что "большинство программистов должно". Я нахожу очень мало прецедентов в toString перечисления, если люди используют это для "дружественного имени", что явно плохой случай использования, поскольку они должны использовать что-то более совместимое с i18n, что в большинстве случаев, используйте метод name().
Ответ 5
name() - это буквально текстовое имя в java-коде перечисления. Это означает, что он ограничен строками, которые могут фактически отображаться в вашем java-коде, но не все желательные строки выражаются в коде. Например, вам может понадобиться строка, которая начинается с числа. name() никогда не сможет получить эту строку для вас.
Ответ 6
Практический пример, когда name() и toString() имеют смысл быть разными, - это шаблон, в котором для определения одноэлементного использования используется однозначное перечисление. Сначала это выглядит неожиданно, но имеет большой смысл:
enum SingletonComponent {
INSTANCE(/*..configuration...*/);
/* ...behavior... */
@Override
String toString() {
return "SingletonComponent"; // better than default "INSTANCE"
}
}
В таком случае:
SingletonComponent myComponent = SingletonComponent.INSTANCE;
assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah
assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better
Ответ 7
Вы также можете использовать что-то вроде кода ниже. Я использовал lombok, чтобы избежать написания шаблонных кодов для геттеров и конструкторов.
@AllArgsConstructor
@Getter
public enum RetroDeviceStatus {
DELIVERED(0,"Delivered"),
ACCEPTED(1, "Accepted"),
REJECTED(2, "Rejected"),
REPAIRED(3, "Repaired");
private final Integer value;
private final String stringValue;
@Override
public String toString() {
return this.stringValue;
}
}