Enum de Java: por qué usar toString en lugar de nombre

Si mira enum api en el name() del método name() dice que:

Devuelve el nombre de esta constante enum, exactamente como se declaró en su statement enum. La mayoría de los progtwigdores deben usar el método toString con preferencia a este, ya que el método toString puede devolver un nombre más fácil de usar. Este método está diseñado principalmente para su uso en situaciones especializadas donde la corrección depende de obtener el nombre exacto, que no variará de un lanzamiento a otro.

¿Por qué es mejor usar toString() ? Quiero decir que String puede ser anulado cuando name () ya es final. Entonces, si usas toString y alguien lo anula para devolver un valor codificado, toda tu aplicación está inactiva … Además, si buscas en las fonts, el método toString () devuelve exactamente el nombre y solo el nombre. Es lo mismo.

Realmente depende de lo que quieras hacer con el valor devuelto:

  • Si necesita obtener el nombre exacto utilizado para declarar la constante enum, debe usar el name() ya que se puede haber toString cadena.
  • Si desea imprimir la constante enum de forma amigable, debe usar toString que puede haber sido anulado (¡o no!).

Cuando siento que puede ser confuso, proporciono un método getXXX más específico, por ejemplo:

 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; } } 

Use name() cuando desee hacer una comparación o use el valor codificado para algún uso interno en su código.

Use toString() cuando quiera presentar información a un usuario (incluido un desarrollador que mira un registro). Nunca confíe en su código en toString() dando un valor específico. Nunca lo pruebe contra una cuerda específica. Si su código se rompe cuando alguien cambia correctamente el retorno toString() , entonces ya estaba roto.

Del javadoc (el énfasis es mío):

Devuelve una representación de cadena del objeto. En general, el método toString devuelve una cadena que “representa textualmente” este objeto. El resultado debe ser una representación concisa pero informativa que sea fácil de leer para una persona . Se recomienda que todas las subclases anulen este método.

name() es un método “incorporado” de enum . Es final y no puedes cambiar su implementación. Devuelve el nombre de la constante enum tal como está escrito, por ejemplo, en mayúsculas, sin espacios, etc.

Compara MOBILE_PHONE_NUMBER y Mobile phone number . ¿Qué versión es más legible? Yo creo el segundo. Esta es la diferencia: name() siempre devuelve MOBILE_PHONE_NUMBER , toString() puede ser anulado para devolver Mobile phone number .

Si bien la mayoría de las personas siguen ciegamente los consejos del javadoc, existen situaciones muy específicas en las que realmente se desea evitar toString (). Por ejemplo, estoy usando enumeraciones en mi código de Java, pero necesitan ser serializadas en una base de datos y viceversa. Si utilicé toString (), técnicamente estaría sujeto a obtener el comportamiento anulado como lo han señalado otros.

Además, también se puede deserializar desde la base de datos, por ejemplo, esto siempre debería funcionar en Java:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.name());

Mientras que esto no está garantizado:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.toString());

Por cierto, me resulta muy extraño que el Javadoc diga explícitamente “la mayoría de los progtwigdores deberían”. Encuentro muy poco caso de uso en el toString de una enumeración, si las personas están usando eso para un “nombre descriptivo” que claramente es un caso de uso deficiente, ya que deberían usar algo más compatible con i18n, que, en la mayoría de los casos, usa el método name ()

name () es literalmente el nombre textual en el código java de la enumeración. Eso significa que está limitado a las cadenas que realmente pueden aparecer en su código Java, pero no todas las cadenas deseables se pueden express en el código. Por ejemplo, puede necesitar una cadena que comience con un número. name () nunca podrá obtener esa cadena por ti.

Un ejemplo práctico cuando name () y toString () tienen sentido para ser diferentes es un patrón en el que se utiliza una enumeración de un solo valor para definir un singleton. Parece sorprendente al principio, pero tiene mucho sentido:

 enum SingletonComponent { INSTANCE(/*..configuration...*/); /* ...behavior... */ @Override String toString() { return "SingletonComponent"; // better than default "INSTANCE" } } 

En tal caso:

 SingletonComponent myComponent = SingletonComponent.INSTANCE; assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better