2010-02-09 19 views
20

Estoy viendo algunos códigos de Java que son mantenidos por otras partes de la compañía, incidentalmente algunos antiguos desarrolladores de C y C++. Una cosa que es ubicuo es el uso de constantes enteras estáticos, tales comoEnumeraciones de Java vs. constantes estáticas

class Engine { 
    private static int ENGINE_IDLE = 0; 
    private static int ENGINE_COLLECTING = 1; 
    ... 
} 

Además de un calificador que carecen de 'final', estoy un poco molesto por este tipo de código. Lo que me hubiera gustado ver, siendo entrenado principalmente en Java de la escuela, sería algo más parecido a

class Engine { 
    private enum State { Idle, Collecting }; 
    ... 
} 

Sin embargo, los argumentos no me falla. ¿Por qué, si es que lo hace, es este último mejor que el anterior?

+4

+1 para hacer constantes 'final'. – uckelman

Respuesta

24

¿Por qué, en todo caso, es el último mejor que el anterior?

Es mucho mejor porque proporciona seguridad y es autodocumentado. Con constantes enteras, debe consultar el documento API para averiguar qué valores son válidos y nada le impide utilizar valores no válidos (o, lo que es peor, constantes enteras que no están relacionadas). Con Enums, la firma del método te dice directamente qué valores son válidos (la función de autocompletado IDE funcionará) y es imposible usar un valor no válido.

la "constante enumeraciones enteros" patrón es por desgracia muy común, incluso en la API estándar de Java (y ampliamente copiado de allí), porque Java no tenía antes de la enumeraciones de Java 5.

+3

+1 porque usted es el único que menciona auto-documentación. Si tiene un método que acepta (o devuelve) un int, que representa algún código, tiene sin doc o fuente ninguna posibilidad de concluir con la semántica de la int Pero la enumeración tiene un nombre para cada valor y la firma está directamente (a través del tipo) conectada a la enumeración. – Mnementh

+1

+1 para "auto-documentación" y "autocompletado IDE funcionará" –

0

El primero es común en el código que comenzó antes de 1.5. En realidad, otro idioma común era definir sus constantes en una interfaz, porque no tenían ningún código.

+0

Pero esa práctica también alienta el uso de la herencia de esas constantes, que es un poco feo. :( –

+0

@David: es el menor de los problemas que causa "enums constantes enteros". –

+0

@Michael: Pero un problema, no obstante. –

5

Al usar un int para referirse a una constante, no está forzando a alguien a usar esa constante. Así, por ejemplo, es posible que tenga un método que toma un estado del motor, a la que alguien podría feliz invocar con:

engine.updateState(1); 

Usando un enumfuerzas del usuario para seguir con la etiqueta explicativa, por lo que es más legible.

1

Hay una situación estática cuando se prefiere constancia (más bien que el código es heredado con una tonelada de dependencia) y es cuando el miembro de ese valor no es/puede no ser finito más tarde.

Imagine si más tarde puede agregar un nuevo estado como Collected. La única forma de hacerlo con enum es editando el código original, que puede ser un problema si la modificación se realiza cuando ya hay un gran código manipulándolo. Aparte de esto, personalmente no veo ninguna razón por la cual no se usa enum.

Sólo mi pensamiento.

+0

Sin embargo, agregar un nuevo estado probablemente requeriría otros cambios en el código (lo que significa el manejo de ese nuevo estado). Entonces el escenario no es muy probable. El código heredado es probablemente el único lugar donde este enfoque es apropiado. – Lajcik

1
  1. Readabiliy - Cuando se utiliza enumeraciones y hacer State.Idle, el lector sabe inmediatamente que se habla de un estado de reposo. Compare esto con 4 o 5.

  2. Tipo de seguridad - Cuando el uso de enumeración, aunque sea por error el usuario no puede pasar un valor incorrecto, como compilador le obligará a utilizar uno de los valores declarados previamente en la enumeración. En el caso de enteros simples, incluso podría pasar -3274.

  3. mantenibilidad - Si quiere añadir un nuevo estado Waiting, entonces sería muy fácil añadir nuevo estado añadiendo una espera constante en su Estado de enumeración sin casuing cualquier confusión.
8

Un extracto de los documentos oficiales, http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html:

Este patrón tiene muchos problemas, tales como:

  • No Typesafe - Desde una temporada es sólo un int puede pasar en cualquier otro valor int donde se requiera una temporada, o agregue dos temporadas juntas (lo cual no tiene sentido).
  • Sin espacio de nombres: debe prefijar constantes de una enumeración con una cadena (en este caso SEASON_) para evitar colisiones con otros tipos de enunciados.
  • Fragilidad: como las enumeraciones son constantes de tiempo de compilación, se compilan en los clientes que las utilizan. Si se agrega una nueva constante entre dos constantes existentes o se cambia el orden, los clientes deben recompilarse. Si no lo son, seguirán ejecutándose, pero su comportamiento será indefinido.
  • Los valores impresos no son informativos. Puesto que solo son simples, si imprime uno, lo único que obtiene es un número, que no le dice nada sobre lo que representa, ni siquiera de qué tipo es.

Y esto apenas lo cubre. Un argumento de una palabra sería que las enumeraciones son más legibles e informativas.

Una cosa más es que las enumeraciones, como las clases. puede tener campos y métodos. Esto le da la opción de incluir información adicional sobre cada tipo de estado en la enumeración en sí.

0

Las enumeraciones también le dan una gran flexibilidad. Dado que los enumerados son esencialmente clases, puede aumentarlos con métodos útiles (como proporcionar una cadena de recursos internacionalizada correspondiente a un cierto valor en la enumeración, convertir hacia atrás y hacia adelante entre las instancias del tipo de enumeración y otras representaciones que puedan ser necesarias, etc.)

1

Las razones de la especificación, que cita Lajcik, se explican con más detalle en Java efectivo de Josh Bloch, artículo 30. Si tiene acceso a ese libro, le recomiendo que lo lea detenidamente. Los Java Enums son clases completas, por lo que obtienes seguridad de tipo de tiempo de compilación. También puedes darles un comportamiento, dándote una mejor encapsulación.

Cuestiones relacionadas