enum.values ​​() - es un orden de enumeraciones devueltas deterministas

105

Tengo una enumeración SOME_ENUM:

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

Será SOME_ENUM.values()siempre devuelven las enumeraciones en el orden de las declaraciones de enumeración: EN_ONE, EN_TWO, EN_THREE? ¿Es una regla o no se garantiza que no se cambie en las próximas versiones de JDK?

Skarab
fuente
1
Repito mi enumeración para completar una lista, que en otro lugar del código leo iterando sobre esta enumeración.
Skarab
11
@MitchWheat Por la misma razón por la que confiaría en un orden de preservación de Lista: porque el JDK es una herramienta que le brinda ciertas garantías y confiar en estas garantías lo ayuda a escribir un código más sucinto y mejor. Es cierto que la pregunta "¿Se garantiza que no se cambiará?" es imposible de responder, ciertamente no puedes confiar en eso, nada tiene esa garantía.
Fletch

Respuestas:

144

La especificación del lenguaje Java utiliza este lenguaje explícito:

@return una matriz que contiene las constantes de este tipo de enumeración, en el orden en que se declaran [Fuente]

Entonces, sí, se devolverán en orden de declaración. Vale la pena señalar que el orden puede cambiar con el tiempo si alguien cambia la clase, así que tenga mucho cuidado con cómo lo usa.

GaryF
fuente
1
Si alguien agrega un valor en el medio en una versión de código posterior, esto podría molestarlo, ya que cambiaría el valor ordinal de otros elementos (consulte el método Enum.ordinal ()). Es mejor no confiar en la posición ordinal como mecanismo de serialización (es decir, no almacenarlo en la base de datos) por esta razón.
Matt
1
¿Enlace a la fuente de esa especificación?
Dan Grahn
Documento de Java 8
Drew Stephens
16

Sí, está garantizado devolverlos en ese orden.

Sin embargo, debe evitar confiar en eso y en el ordinal()valor, ya que puede cambiar después de insertar nuevos elementos, por ejemplo.

Bozho
fuente
+1 por el sabio consejo. Sobre el tema de ordinal (), Effective Java sugiere agregar un campo miembro al tipo de enumeración.
ide
9

Está determinado por el orden en el que se declaran sus valores. Sin embargo, no hay garantía de que usted (u otra persona) no reordene / inserte / elimine valores en el futuro . Así que no debes confiar en el pedido.

Efectivo Java 2nd. Edition dedica su artículo 31 a un tema estrechamente relacionado: use campos de instancia en lugar de ordinales :

Nunca derive un valor asociado con una enumeración de su ordinal; guárdelo en un campo de instancia en su lugar.

Péter Török
fuente
3
"no hay garantía de que alguien no reordene los valores en el futuro", pero es exactamente por eso que quiero confiar en el pedido :-)! Quiero poder reordenar los elementos en el futuro y así cambiar el comportamiento de mi programa. Bloch tiene razón en no confiar en el ordinal y si el ejemplo del autor de la pregunta realmente involucra enumeraciones como EN_TWO, entonces está confiando en el ordinal y no debería hacer esto. Pero confiar en el pedido está perfectamente bien. De hecho, como el orden está garantizado, crear un campo específicamente para el orden sería escribir código redundante, el tipo de cosas que libros como Effective Java te dicen que no hagas.
Fletch
@Fletch, lo siento, no te sigo del todo. Para mí, esto suena a que está tratando de usar enumpara algún propósito para el que no fue diseñado.
Péter Török
digamos que tiene la famosa enumeración "Planet". En su interfaz de usuario, desea enumerar los planetas en el orden de su distancia al sol. ¿Cuál es la mejor manera de lograr esto? Ordenaría las constantes del planeta en el orden correcto dentro de la clase enum y luego simplemente enumeraría la enumeración en la interfaz de usuario. Dado que el pedido es confiable, esto funcionará. Ese es el tipo de cosas de las que estoy hablando. Si un día la Tierra se acerca al sol más que Marte, por supuesto que en ese momento lo primero que tendrá en su mente cálida será mantener su código. Así que vas a tu clase Planet y mueves EARTH antes de MARTE.
Fletch
@Fletch, la Tierra ya está más cerca del Sol que Marte ;-) pero entiendo lo que quieres decir. Sin embargo, en este caso, el orden de los planetas es en realidad una función de su distancia media al Sol, que no es un ordinal simple, por lo que en mi humilde opinión debería almacenarse mejor como un campo distinto para cada planeta. Luego, puede hacer que un comparador trivial compare los planetas en función de su distancia media al Sol y ordenarlos usando este comparador. En mi humilde opinión, esta es una solución limpia e infalible. Considerando que su solución se rompe tan pronto como, por ejemplo, un nuevo colega decide que los planetas obviamente deberían estar listados en orden alfabético ;-)
Péter Török
1
Jajaja ermm sí bueno de todos modos es todo una conspiración, no hay Marte. Inicialmente iba a usar Saturno pero no podía recordar qué planetas estaba cerca, pero el plan de Marte parece haber fracasado :-). De todos modos ... en este caso un comparador sería bueno pero tiene la desventaja de requerir más código, obviamente. Creo que si confía en el orden del código fuente, documentar esto en los comentarios de la clase sería algo bueno. Su colega incluso podría leerlo.
Fletch
7

Las otras respuestas son buenas, pero no comentes sobre esto:

"¿Es una regla o no se garantiza que no se cambie en los próximos lanzamientos de Jdk?"

No creo que existan garantías sobre futuros JDK, por lo que ni siquiera debería preocuparse por ellas. No habría forma de hacerlos cumplir, los futuros clientes potenciales de JDK podrían simplemente decidir incumplir dichas garantías. Es como el sistema parlamentario de Westminster: "Ningún Parlamento puede obligar a un futuro parlamento".

Dicho esto, la historia del JDK revela una excelente consistencia. No realizan muchos cambios importantes, por lo que puede estar bastante seguro de que se conservará el comportamiento especificado (no solo observado) actual .

Fletch
fuente