studio reales proyectos programacion libro introducción incluye herramientas fundamentos fuente español código con avanzado aplicaciones java enums enumeration

reales - ¿Cuáles son las diferencias entre una enumeración de Java y una clase con un constructor privado?



libro de android studio en español pdf (5)

Como las personas han señalado, pierdes values() , valueOf() y ordinal() . Puede replicar este comportamiento con bastante facilidad utilizando una combinación de un Map y una List .

public class Direction { public static final Direction UP = build("UP", 0, -1); public static final Direction DOWN = build("DOWN", 0, 1); public static final Direction LEFT = build("LEFT", -1, 0); public static final Direction RIGHT = build("RIGHT", 1, 0); private static final Map<String, Direction> VALUES_MAP = new LinkedHashMap<>(); private static final List<Direction> VALUES_LIST = new ArrayList<>(); private final int x; private final int y; private final String name; public Direction(int x, int y, String name) { this.x = x; this.y = y; this.name = name; } private static Direction build(final String name, final int x, final int y) { final Direction direction = new Direction(x, y, name); VALUES_MAP.put(name, direction); VALUES_LIST.add(direction); return direction; } public int getX() { return x; } public int getY() { return y; } public static Direction[] values() { return VALUES_LIST.toArray(new Direction[VALUES_LIST.size()]); } public static Direction valueOf(final String direction) { if (direction == null) { throw new NullPointerException(); } final Direction dir = VALUES_MAP.get(direction); if (dir == null) { throw new IllegalArgumentException(); } return dir; } public int ordinal() { return VALUES_LIST.indexOf(this); } @Override public int hashCode() { int hash = 7; hash = 29 * hash + name.hashCode(); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Direction other = (Direction) obj; return name.equals(other.name); } @Override public String toString() { return name; } }

Como puedes ver; El código se vuelve muy torpe muy rápidamente.

No estoy seguro de si hay una manera de replicar una instrucción switch con esta clase; así que perderás eso.

Estaba tratando de entender cómo funciona realmente la enumeración de Java y he llegado a la conclusión de que es muy similar a una clase de Java normal que tiene su constructor declarado privado.

Acabo de llegar a esta conclusión y no se basa en pensar mucho, pero me gustaría saber si me olvido de algo.

A continuación se muestra una implementación de una enumeración simple de Java y una clase de Java equivalente.

public enum Direction { ENUM_UP(0, -1), ENUM_DOWN(0, 1), ENUM_RIGHT(1, 0), ENUM_LEFT(-1, 0); private int x; private int y; private Direction(int x, int y){ this.x = x; this.y = y; } public int getEnumX(){ return x; } public int getEnumY(){ return y; } }

¿Cuál es la diferencia de significado entre el código de arriba y el de abajo?

public class Direction{ public static final Direction UP = new Direction(0, -1) ; public static final Direction DOWN = new Direction(0, 1) ; public static final Direction LEFT = new Direction(-1, 0) ; public static final Direction RIGHT = new Direction(1, 0) ; private int x ; private int y ; private Direction(int x, int y){ this.x = x ; this.y = y ; } public int getX(){ return x; } public int getY(){ return y; } }


Diferencias

  1. Enums extiende java.lang.Enum y gana todas sus características agradables :
    1. Comportamiento singleton automático a través de la serialización correcta.
    2. Método .toString automático legible por .toString en los valores de enumeración sin la necesidad de duplicar sus nombres de enumeración
    3. .ordinal de propósito especial .name y .ordinal
    4. EnumMap clases EnumSet y EnumMap basadas en EnumSet alto rendimiento
  2. Enums son tratados por el idioma especialmente:
    1. Las enumeraciones utilizan una sintaxis especial que simplifica la creación de instancias sin escribir docenas de campos public static final
    2. Enums se pueden utilizar en declaraciones de switch
    3. Enums no se pueden crear instancias fuera de la lista de enumeración, excepto mediante el uso de la reflexión
    4. Las enumeraciones no se pueden extender fuera de la lista de enumeración
  3. Java compila automáticamente cosas extra en enumeraciones:
    1. public static (Enum)[] values();
    2. public static (Enum) valueOf(java.lang.String);
    3. private static final (Enum)[] $VALUES; ( values() devuelve un clon de esto)

La mayoría de estos se pueden emular con una clase diseñada adecuadamente, pero Enum solo hace que sea realmente fácil crear una clase con este conjunto de propiedades particularmente deseables.


Eche un vistazo a esta página de blog , describe cómo se compilan las enumas de Java en el bytecode. Verá que hay una pequeña adición en comparación con su segundo ejemplo de código, que es una matriz de objetos de Direction llamados VALUES . Esta matriz contiene todos los valores posibles para su enumeración, por lo que no podrá hacer

new Direction(2, 2)

(por ejemplo, utilizando la reflexión) y luego usarlo como un valor de Direction válido.

Además, como @ Eng.Fouad explica correctamente, no tiene values() , valueOf() y ordinal() .


La principal diferencia es que cada clase de enum extiende implícitamente la clase Enum<E extends Enum<E>> clase Enum<E extends Enum<E>> . Esto lleva a eso:

  1. enum objetos de enum tienen métodos como name() y ordinal()
  2. enum objetos enum tienen implementaciones especiales para toString() , hashCode() , equals() y compareTo()
  3. objetos enum son adecuados para el operador del switch .

Todo lo mencionado anteriormente no es aplicable para su versión de clase de Direction . Esta es la diferencia de "significado".


Para responder a la pregunta: esencialmente, no hay diferencia entre los dos enfoques. Sin embargo, la construcción de enumeración le proporciona algunos métodos de soporte adicionales como los values() , valueOf() , etc., que tendría que escribir por su cuenta con el enfoque de clase con constructor privado.

Pero sí, me gusta cómo las enumeraciones de Java son casi como cualquier otra clase en Java, pueden tener campos, comportamientos, etc. Pero para mí lo que separa las enumeraciones de las clases simples es la idea de que las enumeraciones son clases / tipos cuyas instancias / miembros Están predeterminados. A diferencia de las clases habituales en las que puede crear cualquier número de instancias, las enumeraciones solo limitan la creación a instancias conocidas. Sí, como ha ilustrado, también puede hacer esto con clases con constructores privados, pero las enumeraciones simplemente lo hacen más intuitivo.