Download Datos enumerados, una introduccion

Document related concepts
no text concepts found
Transcript
Tipo de datos enumerados
Datos de tipo enumerado
Este tipo de datos ha sido incorporado a Java a partir de la versión 1.5. y consiste en la posibilidad de definir nuevos tipos de
datos cuyos posibles valores están limitados a un determinado conjunto dado.
Es una lista ordenada de elementos como constantes. A menos que se indique lo contrario, el primer miembro de un conjunto
enumerado de valores toma el valor de 0 (definición general).
Una enumeración es un tipo de datos, sus miembros son constantes que están escritas como identificadores, pero que toman
valores enteros con signo.
El valor de una enumeración no puede ser leído desde el teclado y asignada a una variable de enumeración.
Las enumeraciones proporcionan a Java tipos enumerados, que definen clases representando un único elemento enumerado. No
proporcionan ningún constructor público, solo métodos estáticos y finales.
Se utiliza la palabra reservada enum para definir datos de este tipo, por ejemplo:
enum Orientacion {NORTE, SUR, ESTE, OESTE}
Para versiones anteriores a la de J2SE 1.5, la forma de definir un determinado conjunto de valores era mediante la utilización
de variables finales (constantes en otros lenguajes):
public class Orientacion
{ public static final int NORTE=1;
public static final int SUR=2;
public static final int ESTE=3;
public static final int OESTE=4;
}
Para referirse a alguno de los valores definidos en las constantes anteriores se utiliza la sintaxis:
Nombre_clase.Constante;
Por ejemplo, Orientacion.ESTE hace referencia al valor 3.
Definición de un tipo enumerado
[public] enum Nombre_tipoEnumerado
{ VALOR1, VALOR2, .. , VALORn;
}
La declaración de un tipo enumerado puede estar en el interior de una clase o en el exterior de ésta, incluso puede estar en un
archivo separado, pero nunca dentro de un método. Para el último caso, el nombre del archivo será el mismo que el del tipo
enumerado y llevará la extensión .java, y se compilará como cualquier archivo .java.
Por ejemplo, para el caso que se presente al principio de este tema, el tipo enumerado quedará de la forma siguiente:
enum Orientacion
{NORTE, SUR, ESTE, OESTE;} //El ; (punto y coma) puede ser opcional.
Una enumeración es un tipo especial de clase, clase que hereda de java.lang.Enum. A diferencia de las clases estándares, una
clase de enumeración no permite el uso del operador new para la creación de objetos. Cada uno de los valores de la
enumeración representa uno de los posibles objetos de la clase, los cuales serán creados de forma implícita al hacer referencia
en el código estos valores.
Además de los métodos heredados por la clase Enum, las enumeraciones disponen del método values(), que devuelve un
arreglo con todos los objetos de la clase.
maria eugenia puga nathal
Página 1
08/08/2017
Tipo de datos enumerados
Creación de un objeto enumeración
Una vez que se ha definido la enumeración, se puede crear una variable de ese tipo, aun que se trata de una clase, no se
requiere del operador new como en las clases comunes, para este caso solo se requiere declarar una variable del tipo de la
enumeracion en cuestión y se le asigna el valor que se requiere, como si se tratara de un dato de tipo primitivo, por ejemplo:
Orientacion orienta; // aquí solo se declara la variable, ya mas adelante se le puede asignar un valor como si se tratará de un
//dato primitivo, con la diferencia que siempre hay que hacer referencia del tipo que lo contiene.
orienta=Orientcion.NORTE; // se asigna una constante de enumeración a la variable antes declarada.
Orientacion orienta=Orientacion.SUR; //aquí se declara una variable y se le asigna un valor, es decir, se inicializa.
Mostrar todos los valores definidos en una enumeración, siguiendo el ejemplo anterior tenemos:
for(Orientacion orienta:Orientacion.values())
{ System.out.println(orienta);
}
Las enumeraciones a diferencia de los objetos, pueden compararse a través del operador = = o haciendo uso del método
equals(), además de utilizarse como expresión en la instrucción switch, para este último, cuando se define la sentencia case,
solo se pone el nombre de la constante de enumeración sin la referencia del tipo que la define, si se hace la referencia, marca
error de sintaxis al momento de la compilación, es decir pondríamos case SUR, en lugar de case Orientacion.SUR.
switch(orienta)
{case NORTE : sentencias; break;
case SUR : sentencias; break;
:
}
Métodos
Existen métodos para el manejo de datos enumerados, entre estos se encuentran:
values()  devuelve todos los valores de la enumeración en una colección
valueOf(cadena)  devuelve la constante de enumeración que corresponde a un parámetro de tipo String.
Orientacion o=varOrientacion.valueOf(”SUR”);
Regresa: Orientacion.SUR, la cual se almancena en la variable enumerada o
name()  devuelve el nombre de la constante en a enumeración.
Orientacion.SUR.name();
Regresa: SUR
ordinal()  devuelve la posición de la constante declarada, siendo la inicial 0.
Orientacion.SUR.ordinal();
Regesa: 1
compareTo()  Compara el objeto actual con el objeto de la enumeración que se especifique, devolviendo un número
negativo, cero, o un número positivo dependiendo de que el objeto actual sea menor, igual o mayor que el objeto especificado
de la enumeración, respectivamente.
Orientacion.SUR.compareTo(Orientacion.OESTE);
Regesa: -2, por que SUR está dos posiciones mas a tras que OESTE en la declaración de la enumeración.
toString()  regresa una cadena la cual correspondo con el objeto enumerado contenido en la variable enumerada.
Orientacion c=Orientacion.SUR;
String cad=c.toString();
Regresa ”SUR” el cual se almacena en la variable cad.
Resumen
En resumen, las características de los tipos enumerados en Java son:
- Son clases especiales de java y hereden implícitamente de la clase java.lang.Enum.
- No tienen constructores, aunque sean objetos, no tienen el método constructor asociado a la creación de objetos, pero
si como parte de su diseño.
maria eugenia puga nathal
Página 2
08/08/2017
Tipo de datos enumerados
-
-
-
Son public, static y final. Con el modificador de acceso public nos da las facilidades para que puedan ser accedidos
sin restricciones. Al ser de tipo static, sus valores no pueden cambiar una vez definidos, y son de tipo final porque,
aunque sean clases, no pueden ser heredadas.
Tienen métodos asociados, como los que se acaban de mencionar en el apartado anterior.
Al ser al final de cuentas una clase, un dato enumerado en Java puede contener la definición de variables de instancia
y métodos, e incluso al método main().
Es muy común hacer uso del ciclo for-each para recorrer los datos que componen a la enumeración.
A cada elemento que se define en la enumeración se le asocia internamente un valor entero positivo, comenzando
desde 0 (cero).
A los elementos de una enumeración se les puede conocer como constantes de enumeración. Y cada uno está
implícitamente declarado como public static final de la clase (enumeración) que lo contiene. Su tipo es el tipo de la
enumeración que lo contiene, por ejemplo, la constante de enumeración SUR, pertenece al tipo Orientacion.
No pueden heredar ni ser heredadas.
Ejemplos
1. editar el código siguiente:
public enum Estaciones
{primavera, verano, otono, invierno}
2. grabarlo con el nombre de Estaciones.java
3. compilar el archivo anterior
4. Editar en un archivo diferente el código siguiente:
import java.io.*;
// definición de la enumeración Frutas
public class EnumList
{enum Frutas {naranja, lima, manzana, pera, sandia, durazno}
public static void main(String arg[])throws IOException
{String cad,cad2;
int res=0;
BufferedReader ent=new BufferedReader(new InputStreamReader(System.in));
Frutas fruta[]=Frutas.values(); // pasa los valores de la enumeración a un arreglo del mismo tipo Enumerado
// ciclo para imprimir los valores de Frutas
System.out.println("----> Frutas <----");
for (Frutas f:Frutas.values())
{System.out.println(f);}
System.out.println();
System.out.println();
System.out.println("---->Estaciones<---");
// ciclo para imprimir los valores del tipo enumerado Estaciones, el cual fue diseñado fuera de esta clase.
for (Estaciones e:Estaciones.values()) // ciclo para imprimir los valores del tipo enumerado Estaciones
{System.out.println(e);}
System.out.println();
// se pide una cadena y se evalua a través de un switch
System.out.print("Proporciona un estacion --> ");
cad=ent.readLine();
switch(Estaciones.valueOf(cad))
{case primavera: System.out.println(cad); break;
case verano:System.out.println(Estaciones.valueOf(cad).ordinal());break;
case otono:System.out.println(Estaciones.valueOf(cad).toString());break;
case invierno:System.out.println("invierno");break;
}
System.out.println();
for (Frutas f:fruta) //ciclo que imprime los valores de Frutas que se pasaron al arreglo fruta
{System.out.println(f);}
System.out.println(); System.out.println();
maria eugenia puga nathal
Página 3
08/08/2017
Tipo de datos enumerados
for (int i=0;i<fruta.length;i++) //ciclo que imprime los valores de Frutas que se pasaron al arreglo fruta de la forma antigua
{ System.out.println(fruta[i]);}
System.out.println();
// se pide una estacion y se evalua si esta antes o después de otra de las estaciones
System.out.print("proporciona otra estacion --> ");
cad2=ent.readLine();
if((res=Estaciones.valueOf(cad).compareTo(Estaciones.valueOf(cad2)))<0)
System.out.println(cad2+" esta despues de "+cad);
else System.out.println(cad2+" esta antes de "+cad);
System.out.println("resultado de la comparacion "+res);
}
}
5. grabar el archivo con el nombre EnumList.java
6. compilar el archivo
7. ejecutar el archivo
Si cuando se captura una cadena que hará referencia a algún valor de la enumeración, éste no coincide con los valores
predeterminados, se lanzara la excepción: IllegalArgumentException, por lo que es aconsejable manejar un try – catch para la
captura de ésta y evitar que nuestro programa aborte.
El código que viene a continuación, es la última parte del ejemplo anterior, la parte de azul es lo que se le agregó:
System.out.print("proporciona otra estacion --> ");
cad2=ent.readLine();
try{
if((res=Estaciones.valueOf(cad).compareTo(Estaciones.valueOf(cad2)))<0)
System.out.println(cad2+" esta despues de "+cad);
else System.out.println(cad2+" esta antes de "+cad);
System.out.println("resultado de la comparacion "+res);
}
catch(IllegalArgumentException e)
{System.out.println("el dato proporcionado no forma parte de la enumeracion Estaciones");}
Como ejercicio, corregir el ejemplo.
Otro ejemplo:
public enum DiasSemana
{lunes, martes, miercoles, jueves, viernes, sabado, domingo}
Grabar como DiasSemana.java y compilar
import java.io.*;
public class ejemploDiasSemana
{public static void main(String arg[]) throws IOException
{BufferedReader ent=new BufferedReader(new InputStreamReader(System.in));
DiasSemana dia[]=DiasSemana.values(); // se crea un arreglo que contendrá todos los datos de la enumeracion
String x;
int valor=0;
boolean ban=false;
DiasSemana usuario=DiasSemana.lunes; // se declara e inicializa una variable de tipo DiasSemana
DiasSemana dato=DiasSemana.miercoles; // se declara e inicializa una variable de tipo DiasSemana
//Se imprimen los datos de la enumeración almacenados en el arreglo dia
for(DiasSemana d:dia)
{System.out.println(d);}
System.out.println();
//Se imprimen los datos de la enumeración directamente a través del uso del método values()
for (DiasSemana d:DiasSemana.values())
{System.out.println(d+" valor ordinal "+d.ordinal());}
System.out.println();
//se le solicita al usuario que proporcione un día de la semana, y se verifica que se un dato válido
do{
try {System.out.println("Proporciona un dia de la semana");
maria eugenia puga nathal
Página 4
08/08/2017
Tipo de datos enumerados
x=ent.readLine();
usuario=DiasSemana.valueOf(x);
System.out.println();
ban=true;
}
catch(IllegalArgumentException e)
{System.out.println("Valor no valido en la enumeracion");}
}
while(ban==false);
switch(usuario)
{case lunes:System.out.println("el dia es "+usuario);break;
case martes:System.out.println("el dia es "+usuario);break;
case miercoles:System.out.println("el dia es "+usuario);break;
case jueves:System.out.println("el dia es "+usuario);break;
case viernes:System.out.println("el dia es "+usuario);break;
case sabado:System.out.println("el dia es "+usuario);break;
case domingo:System.out.println("el dia es "+usuario);break;
}
System.out.println();
valor=usuario.compareTo(dato);
System.out.println("comparacion "+valor);
if(valor==0)
{System.out.println("el dia del usuario es igual a "+dato);}
else if(valor<0)
{System.out.println("el dia "+usuario+" esta antes del dia "+dato);}
else {System.out.println("el dia "+usuario+" esta despues del dia "+dato);}
}
}
Como ya se menciono, una enumeración en Java al final de cuentas es un tipo de clase, aunque no se instancia un enum
utilizando el operador new, éstos tienen casi las mismas capacidades de las clases. Esto es lo que lo hace diferente con respecto
a otros lenguajes de programación que también soportan la definición y uso de datos enumerados, ya que dentro de la
enumeración podemos definir constructores, variables de instancia, métodos, e incluso interfaces.
Es importante saber y entender que cada constante de la enumeración es un objeto de su propio tipo enumerado. Así, cuando se
define un constructor para un enum, el constructor es llamado cuando cada constante de enumeración es creada. Por ejemplo:
public enum Calificacion
{EXCELENTE(10), MUY_BIEN(9),BIEN(8),REGULAR(7),MALO(6),PESIMO(5);
private int valor; //variable de instancia
Calificacion(int v) //método constructor
{valor=v;}
public int regresaValor() //metetodo que regresa el valor asociado al parámetro de la constante de enumeración
{return valor;}
}
public class PruebaCalificacion
{public static void main(String arg[])
{Calificacion cal=Calificacion.BIEN;//implicitamente se llama al método constructor y se envía como parámetro el valor de 8,
//el cual se asigna a la variable de instancia valor
System.out.println(cal+" valor ordinal "+cal.ordinal()+" valor asignado al parametro "+cal.regresaValor());
}
}
Salida:
BIEN valor ordinal 2 valor asignado al parametro 8
Otro ejemplo:
public enum Calificacion2
{EXCELENTE(10), MUY_BIEN(9),BIEN(8),REGULAR(7),MALO(6),PESIMO;
private int valor;
Calificacion2()//método constructor para el caso de la constante que no tiene parámetro
{valor=0;}
maria eugenia puga nathal
Página 5
08/08/2017
Tipo de datos enumerados
Calificacion2(int v)//método constructor para el caso de las constantes que si tienen parámetro
{valor=v;}
public int regresaValor()
{return valor;}
//puede ir el método main()
public static void main(String arg[])
{
for(Calificacion2 c:Calificacion2.values())
{System.out.println(c+" valor ordinal "+c.ordinal()+" valor asignado al parametro "+c.regresaValor());}
}
}
Salida:
EXCELENTE valor ordinal 0 valor asignado al parametro 10
MUY_BIEN valor ordinal 1 valor asignado al parametro 9
BIEN valor ordinal 2 valor asignado al parametro 8
REGULAR valor ordinal 3 valor asignado al parametro 7
MALO valor ordinal 4 valor asignado al parametro 6
PESIMO valor ordinal 5 valor asignado al parametro 0
Otra cosa que podemos hacer cuando definimos una enumeración, es crear métodos dentro de cada una de las constantes, estos
deberán ser definidos posteriormente como métodos abstractos, y cada constante implementarlos de acuerdo a sus necesidades,
por ejemplo:
public enum Operacion
{SUMA {double eval(double x, double y){return x+y;}},
RESTA {double eval(double x, double y){return x-y;}},
MULTIPLICACION {double eval(double x, double y){return x*y;}},
DIVISION {double eval(double x, double y)
{try
{return x/y;}
catch(ArithmeticException e)
{return 0;}
}
};
abstract double eval(double x, double y);
}
public class ejemploOperacion
{public static void main(String arg[])
{double x=10.5;
double y=5.0;
for (Operacion o:Operacion.values())
{System.out.println(o.eval(x,y));}
}
}
Clase EnumSet
EnumSet es una colección específicamente diseñada para usarla con valor de tipo enum. Permite la construcción de conjuntos
de datos enumerados. EnumSet no define métodos constructores, en lugar de ello, utiliza métodos que permiten definir
instancias de EnumSet, por ejemplo los métodos allOf(), range(), entre otros.
Todos los métodos que ofrecen pueden en un momento dado generar un NullPointerException en caso de que al tratar de
formarse el conjunto se genere un problema. Los métodos copyOf() y range() pueden también generar la excepción
IllegalArgumentException.
maria eugenia puga nathal
Página 6
08/08/2017
Tipo de datos enumerados
Definición de un conjunto (una instancia de la clase EnumSet)
EnumSet <tipo de dato enumerado> variable=EnumSet.metodo(parametros);
Por ejemplo:
EnumSet <Calificacion> altas=EnumSet.of(Calificacion.EXCELENTE,Calificacion.MUY_BIEN);
Algunos de sus métodos
allOf(archivoEnum.class);  genera un conjunto con todos los elementos de la enumeración, el
parámetro es el nombre del archivo .class generado de la enumeración.
noneOf(archivoEnum.class);  genera un conjunto vacío de la enumeración, el parámetro es el nombre
del archivo .class generado de la enumeración.
range(rango de valores);  genera un conjunto con los elementos indicados en el rango, por ejemplo:
EnumSet <Calificacion> aprobatorias=EnumSet.of(Calificacion.EXCELENTE,Calificacion.REGULAR);
of(lista de constantes de enumeracion);  genera un conjunto formado por la o las constantes de
enumeración que se enlisten dentro del parámetro. Por ejemplo:
EnumSet <Calificacion> altas=EnumSet.of(Calificacion.EXCELENTE,Calificacion.MUY_BIEN);
EnumSet <Calificacion> bajas=EnumSet.of(Calificacion.BIEN,Calificacion.REGULAR);
EnumSet <Calificacion> reprobatoria=EnumSet.of(Calificacion.PESIMA);
complementOf(conjunto o lista de constantes de enumeracion);  genera un conjunto con los elementos
que no están bien sea en el conjunto que se ha enviado como parámetro o de la lista de
elementos que se envío como parámetro. Por ejemplo:
EnumSet <Calificacion> aprobatoria=EnumSet.complementOf(Calificacion.PESIMA);
EnumSet <Calificacion> aprobatoria=EnumSet.complementOf(reprobatoria);
copyOf(conjunto);  genera un conjunto a partir de los elementos almacenados en el conjunto
especificado en el parámetro.
Ejemplo
import java.util.EnumSet;
public class ejemploEnumSetDiasSemana
{public static void main(String arg[])
{for (DiasSemana d:EnumSet.range(DiasSemana.martes,DiasSemana.viernes))
{System.out.println(d);}
System.out.println();
EnumSet <DiasSemana> todos=EnumSet.allOf(DiasSemana.class);
EnumSet <DiasSemana> ninguno=EnumSet.noneOf(DiasSemana.class);
EnumSet <DiasSemana> rango=EnumSet.range(DiasSemana.lunes,DiasSemana.viernes);
EnumSet <DiasSemana> sinR=EnumSet.of(DiasSemana.lunes, DiasSemana.jueves, DiasSemana.sabado,
DiasSemana.domingo);
EnumSet <DiasSemana> conR=EnumSet.complementOf(sinR);
System.out.println("TODOS");
for (DiasSemana d:todos)
{System.out.println(d);}
System.out.println();
System.out.println("NINGUNO");
for (DiasSemana d:ninguno)
{System.out.println(d);}
System.out.println();
System.out.println("RANGO");
for (DiasSemana d:rango)
{System.out.println(d);}
System.out.println();
System.out.println("con R");
for (DiasSemana d:conR)
{System.out.println(d);}
System.out.println();
maria eugenia puga nathal
Página 7
08/08/2017
Tipo de datos enumerados
System.out.println("sin R");
for (DiasSemana d:sinR)
{System.out.println(d);}
System.out.println();
}
}
maria eugenia puga nathal
Página 8
08/08/2017