Está en la página 1de 21

10.

- Clases complementarias

TEMARIO DE CURSO
PROGRAMACIÓN JAVA SE

Iñaki Martín

CAPÍTULO 10
CLASES COMPLEMENTARIAS
©

Wrappers, Math, String, Date.


Temario de curso JavaSE

ENUMERADOS

© Iñaki Martín

Este obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-SinObraDerivada 4.0 Internacional.
10.- Clases complementarias Clases genéricas Java 2

Clases de uso común en Java


• Java ofrece más de 10000 clases sólo en la distribución estándar de JSE.
• De las clases de uso genérico (las que no se dedican a una operativa específica, como las colecciones o las

clases de ficheros) hemos usado algunas de ellas, por necesidad (como Scanner, BufferedReader, etc),
pero de las clases más habituales sólo hemos visto prácticamente String.
Iñaki Martín

• En este capítulos vamos a ver más clases usadas en la programación java, dentro de las que podemos
llamar de uso genérico, y luego se tratarán temas como ficheros, base de datos, comunicación, etc, donde
se verán clases especificas para cada una de esas materias.
©

• Para tratar estas clases genéricas, veremos en este capítulo:


- Clases envoltorio
Temario de curso JavaSE

- Clases básicas tipo (Math, String, Fechas )


- Enumerados
- Clases específicas de diversas materia
10.- Clases complementarias Diagrama de paquetes y grupos de clases 3

Diagrama de paquetes
• Como introducción, se ofrece este gráfico con la organización de los paquetes básicos de Java:

Iñaki Martín
©
Temario de curso JavaSE
10.- Clases complementarias Clases básica: clases envoltorio 4

Clases envoltorio (wrappers)


๏ Los tipos de datos primitivos de java (int, double, char,…) no son clases, no tienen atributos ni métodos.
๏ Hay ciertas cosas que en java solo se pueden hacer con objetos, no con tipos primitivos

๏ Para ello, en java hay clases para crear objetos con la misma información de los tipos primitivos
๏ A estas clases se les llama clases envoltorio (o wrapper), son estas
Iñaki Martín

• Byte , almacena valores byte. • Boolean , almacena valores boolean.


• Short , almacena valores short. • Float , almacena valores float.
• Integer , almacena valores int. • Double , almacena valores double.
• Long , almacena valores long. • Character , almacena valores char.
©

๏ En las líneas siguientes, la diferencia entre la variable h y m, es que m tiene métodos y atributos que se pueden
usar como con cualquier otra clase de Java.
Temario de curso JavaSE

๏ Los objetos de wrappers se pueden usar exactamente igual que su correspondiente tipo primitivo. Por ejemplo,
si son numéricos, se pueden sumar, restar, etc, operando incluso con su correspondiente primitivo…
int h = 23;
Integer num = 34;
int x = num + 12 - h;

Pero cuidado, en estos casos, internamente, se convierte num en primitivo, se incrementa y luego se vuelve a crear
otro objeto y asigna a num. Por eso no es aconsejable usar objetos contenedores si se realizan muchas operaciones,
y usarlos solo para lo necesario.
๏ Además, como son objetos, se pueden construir como si fuera un primitivo, o de forma tradicional (con new). En este
caso, en el constructor (entre paréntesis) se puede poner un int, un string, un char…
Integer m = 34; // m vale 34
Integer m = new Integer (34); // m vale 34
Integer m = new Integer (“34”); // m vale 34
10.- Clases complementarias Autoboxing y autounboxing 5

Autoboxing y Autounboxing
๏ Se ha visto que el casting entre tipos numéricos primitivos se hace de modo implícito o explícito. Ahora, al añadir los
wrappers entre nuestros elementos de programación, se nos plantea otro problema. ¿Si deseo convertir un tipo
primitivo en un wrapper, qué he de hacer? ¿Se hace un casting implícito? ¿Se ha de hacer explícito? ¿Cómo?

๏ Miremos las lineas siguientes:


Iñaki Martín

Integer x = new Integer(34); // Declaración formal de Integer


int n = 5;
Integer num = n; // Autoboxing
Character g = ‘h’; // Autoboxing

๏ La primera linea es una declaración formal de un objeto, que es perfectamente válida también para un objeto
©

envoltorio. Sin embargo, en las dos últimas lineas vemos que se asigna un valor primitivo directamente a un objeto.
Esto es perfectamente válido. El tipo primitivo se convierte implícitamente en un objeto envoltorio.
Temario de curso JavaSE

A esta operación se la denomina autoboxing (un Integer crea un objeto num con contenido 5).
๏ Lo contrario a autoboxing es autounboxing, que también esta permitido y se realiza también implícitamente:
Integer num = 23;
int n = num; // Autounboxing

๏ Pero cuidado, el autoboxing o autounboxing se realiza entre primitivos y wrappers de la misma naturaleza (int con
Integer, double con Double). Entre tipos diferentes no se puede:

int h;
Double dob = 33.2;
h=dob; // ERROR, no puedo asignar un Double a un int
h = (int) dob; // ERROR, no puedo convertir un Double en un int
h = dob.intValue(); // SI, asi puedo convertir un Double en un int
10.- Clases complementarias Clases básica: clases envoltorio. Uso 6

Uso clases envoltorio


• Las clases envoltorio tienen la misma funcionalidad que un tipo primitivo, por lo que se pueden hacer
operaciones matemáticas con objetos de clases de envoltorio;

Integer num = 34;


num ++;
Iñaki Martín

• En este caso, internamente, se convierte num en primitivo, se incrementa y luego se vuelve a crear otro objeto
de tipo Integer y asigna a num. Por eso no es aconsejable operar aritméticamente con objetos contenedores,
pues crean y destruyen varias copias en el proceso.
Las clases envoltorio, pues, se deben usar cuando se necesite, pero nunca para operaciones aritméticas
©

masivas.
• Una de las utilidades mayores de las clases envoltorio son los atributos y métodos estáticos que
Temario de curso JavaSE

proporcionan (como estáticos que son., se pueden invocar con la clase directamente, sin necesidad de crear
ningún objeto).
Veamos algunos ejemplos de los métodos estáticos más útiles de las clases contenedoras:

Integer int .parseInt(String s) Devuelve un entero, que es la cadena s convertida a número.


Al igual que para Integer, existe un Double.parseDouble(String s), y los correspodientes a
Long, Float, etc
String n="34";
int p = Integer.parseInt(n); // p valdrá 34

Integer int signum(int unInt) Devuelve el signo del integer unInt. Devuelve -1 si el valor es negativo, 0 si el valor especificado
es 0, y 1 si es positivo
10.- Clases complementarias Clases básicas tipo matemáticas 7

Clase Math
• En el análisis de clases mas comunes usadas, se ve a continuación los métodos que (todos ellos estáticos)
ofrece la clase Math, para realizar operaciones aritméticas complejas:

Math int .max(unNumero1, unNumero2) Devuelve el mayor de los dos numeros, en el formato de dichos
Iñaki Martín

números (si ambos son int, devuelve int, etc)


Math int .min(unNumero1, unNumero2) Devuelve el menor de los dos numeros, en el formato de dichos
números (si ambos son int, devuelve int, etc)
Math int .abs(unNumeroDecimal) Devuelve el valor absoluto del parámetro (double, float, etc…)
Math double .pow(base,exponente) Devuelve un double, el parametro base elevado a parametro exponente
©

Math double .random() Devuelve un numero aleatorio desde 0.0 hasta 1 (exlusive)
Math int .round(unNumeroDecimal) Devuelve el parametro pasado redondeado, esto es, el numero
entero más proximo al valor pasado. El tipo que devuelve es:
Temario de curso JavaSE

- si el tipo del parámetro es double, devuelve un long,


- si el tipo del parámetro es float, devuelve un int,
Math double .sin(numeroDouble) Devuelve el seno del angulo pasado por parámetro
Al igual que sin() existen otros muchos métodos para cálculos trigonométricos (cos(), tan(), … )
10.- Clases complementarias Clases básicas tipo String 8

Clase String

• Además de los métodos ya vistos anteriormente de la clase String, comentamos ahora unos cuantos más:

String int indexOf(String str, int fromIndex) Devuelve la posición en la que se encuentra str dentro de la cadena-objeto.
Opcionalmente se puede añadir un indice inicial desde el que empezar a buscar.
Iñaki Martín

String int lastIndexOf(String str) Devuelve el índice dentro de la cadena-objeto con la última aparición de la cadena str
String String replaceAll(String regex, String rep) Reemplaza en la cadena-objeto toda aparición de regex por la cadena rep
String String replace(char oldChar, char newChar) Devuelve un String resultante de reemplazar el char oldChar por newChar dentro de la
cadena-objeto
String String[] split(String regex) Devuelve un array de Strings, troceando la cadena objeto usando como separador la
cadena regex
©

String boolean startsWith(String prefix) Indica si la cadena-objeto comienza por prefix


String char[] toCharArray() Convierte la cadena-objeto en array de char
String String trim() Elimina de la cadena-objeto los espacios iniciales y finales
Temario de curso JavaSE

String String valueOf(parametro) Convierte el parámetro a un String.


10.- Clases complementarias Trabajando con fechas en Java 9

Clase Date
• La clase base y las mas antigua es Date.
• Se han creado muchas heredadas de ella, más y mejores, y ahora tiene muchos metodos obsoletos (deprecated),
aunque algunos metodod se pueden usar en conjunción con las clases derivadas , como Calendar o

GregorianCalendar.
Iñaki Martín

Date dd = new Date();


• Para crear un objeto con la fecha actual: System.out.println(dd); // Mon Jul 03 17:07:09 CEST 2017

• La fecha se guarda como el numero de milisegundos transcurridos desde 01-01-1970, que se pueden consultar con el
método getTime():
System.out.println(dd.getTime()); // 1499094652787
System.out.println(dd.getTime() + 1000); // 1499094653787
©

Clase Calendar
Temario de curso JavaSE

• Es abstracta, para crear un objeto usa el método getInstance(): Calendar cc = Calendar.getInstance();

• Este método devuelve la fecha y hora actual, en un formato con el que se puede operar, pero no visualizar
• Para usarle mejor parsarla a una instancia de Date con .getTime(): Date d = cc.getTime();

• Clase GregorianCalendar

• GregorianCalendar es la heredera de Calendar diseñada para modelar los calendarios tradicionales occidentales.
• Posee todos los métodos de Calendar ( y por ende, de Date) y añade poco más interesante, salvo el método
isLeapYear()

Nota:
El uso de estas clases es clásico en versiones de Java anteriores a la 8.
Si trabajamos con Java 8 o superior, se recomienda el uso de las nuevas clases incluidas dentro del paquete
java.time para el manejo de tiempos y fechas (clases como Clock, Duration, Instant, LocalDate, LocalTime,
MonthDay, OffsetDateTime, OffsetTime, Period, Year, YearMonth, ZonedDateTime, ZoneId y ZoneOffset).
10.- Clases complementarias Clases básicas tipo fecha (II) 10

Principales metodos de Date, Calendar y GregorianCalendar


after(Date date) Devuelve un boolean, true si el objeto fecha que invoca el método es una fecha posterior a la que se
Date boolean
indica por parámetro, false en caso contrario
before(Date date) Devuelve un boolean, true si el objeto fecha que invoca el método es una fecha anterior a la que se

Date boolean
indica por parámetro, false en caso contrario
compareTo(Date date) Compara el objero fecha que invoca al método con el parámetro pasado. Devuelve un int,
Iñaki Martín

- 0 si ambas fechas son iguales


Date int
- un valor negativo si el objeto es anterior al parámetro
- un valor positivo si el objeto es posterior al parámetro
.getTime() Devuelve la hora del objeto en formato completo (se puede formatear luego):
2014/12/16 08:11:00 (Diciembre 16 de 2014)
Date long NOTA: Date guarda la información de la fecha y hora como un número de tipo long que representa la
©

cantidad de milisegundos transcurridos desde el día 1 de Enero de 1970 hasta el momento de la


creación del objeto. Es es el número que puede ser obtenido a través de método getTime()
setTime(long time) Asigna al objeto que invoca al método una fecha y hora, un long, el número de milisegundos que han
Temario de curso JavaSE

Date void
pasado desde el 1-1-1970
.get(nn) Devuelve un entero que puede ser cualquier parte de la fecha, dependiendo del parámetro nn, para lo
cual se usan las constantes que provee Calendar: YEAR para año, MONTH, DAY, DAY_OF_WEEK…
Date int int f= cc.get(Calendar.DAY_OF_MONTH // Cuidado: Los meses van numerados desde 0 a 11
if (cc.get(Calendar.MONTH) == Calendar.JUNE {
System.out.println("ES JUNIO”); }
Calendar void
.set(int ele, int valor) Cambia el valor de la hora del objeto. Se indica el valor a cambiar y el nuevo valor
cc.set(Calendar.MONTH,Calendar.JANUARY) ; cc.set(Calendar.YEAR, 1980);
Calendar void .set(int a, int m, int d) Variante sobrecargada: los parámetros corresponden a año, mes y día: cc.set(2004,1,7);
.add(int patron, int n) Incrementa la fecha-objeto en la cantidad de unidades de patron, indicada por el valor n. Advertir que
Calendar Date usando un en negativo se puede “decrementar” la fecha.
cal.add(Calendar.SECOND,52); cal.add(Calendar.MONTH, -3);
Calendar Date
.rollint patron, int num) ídem add, pero si un contador se pasa no aumenta el resto de datos. Por ejemplo, si tengo un mes 10, y
hago un roll ( Calendar.MONTH, 4), el mes se va a febrero, pero el año no avanza
Gregorian isLeapYear( int a) Indica si el año del parámetro (a) es bisiesto o no
Calendar boolean
10.- Clases complementarias Clases básicas tipo fecha (II) 11

Trabajando con fechas en Java

// CREAR OBJETOS CON FECHA DE HOY


Date d1 = new Date();

Calendar cc = Calendar.getInstance();
Date d2 = cc.getTime();
Calendar c2 = new GregorianCalendar();
Iñaki Martín

System.out.println(d1); // Mon Jun 03 18:18:47 CEST 2013


System.out.println(d2.getTime()); // 1499094652787
System.out.println(d2.getTime() + 1000); // 149653787

// IDENTIFICAR ELEMENTOS DE UNA FECHA:


int año = cc.get(Calendar.YEAR);
int mes = cc.get(Calendar.MONTH);
©

int dia = cc.get(Calendar.DAY_OF_MONTH);


int hora = cc.get(Calendar.HOUR_OF_DAY);
int minuto = cc.get(Calendar.MINUTE);
int segundo = cc.get(Calendar.SECOND);
Temario de curso JavaSE

// CREAR UNA FECHA NUEVA O CAMBIAR ALGUN ELEMENTO


cc.set(2013, 5, 1); // asigna año, mes, día
cc.set(2013, 5, 1, 3, 45, 12); // asigna año, mes, día, hora, minuto, segundo
cc.set(Calendar.YEAR, 2015); // cambiar solo el año, a 2015

// SUMAR Y RESTAR ELEMENTOS A FECHAS


cc.add(Calendar.DAY_OF_MONTH, 10); // sumar 10 días a la fecha actual
cc.add(Calendar.MINUTE, 10); // sumar 10 minutos a la hora actual
cc.add(Calendar.YEAR, -2); // restar 2 años a la fecha actual

// MEDIR TIEMPO TRANSCURRIDO EN EJECUCION


try {
long ini = System.currentTimeMillis();
Thread.sleep(2000);
long fin = System.currentTimeMillis();
System.out.println("Diferencia en seg: " + ((fin - ini) / 1000)); // escribe 2
} catch (Exception e) { }
10.- Clases complementarias Fechas y String, intercambio de datos 12

Conversiones entre Date y String


• Se puede dar formato a los objetos de tipo fecha, para obtener conversiones a un String con el modelo de
texto deseado, así como el procedimiento inverso. Para ello se usa la clase SimpleDateFormat (que hereda de

DateFormat, por lo que tiene los mismos métodos que ésta):


Iñaki Martín

✓ Convertir un objeto Date en un String con formato. Se usa el método .format() de SimpleDateFormat :
Crear un objeto de SimpleDateFormat con un formato específico, y luego, usar el método format() sobre
una objeto Date para obtener un String (ver más adelante posibilidades de formato):
Calendar cc = Calendar.getInstance();
Date fecha = cc.getTime();
©

// estas dos son las lineas interesantes


SimpleDateFormat miFormato = new SimpleDateFormat("dd/MM/yyyy");
String fechaEnTexto = miFormato.format(fecha);
Temario de curso JavaSE

System.out.println(fechaEnTexto);
String fechaEnTexto2 = new SimpleDateFormat("dd/MM/yyyy").format(fecha); // en una sola linea

✓ Convertir un String en un objeto Date. Se usa el método .parse() de SimpleDateFormat :


Crear un objeto de SimpleDateFormat con un formato específico, y luego, usar el método parse() sobre un
String con dicho formato para obtener un objeto Date. Hay que añadir control de excepciones:
String strFecha = "23/12/2013";
try {
// estas dos son las lineas interesantes
SimpleDateFormat miFormato2 = new SimpleDateFormat("dd/MM/yyyy");
Date fecha2 = miFormato2.parse(strFecha);
System.out.println(fecha2.toString());
Date f =new SimpleDateFormat("dd/MM/yyyy").parse("21/12/2016"); // en una sola linea
} catch (ParseException e) {
e.printStackTrace();
}
10.- Clases complementarias Fechas y String, intercambio de datos 13

๏ Se ofrece un ejemplo de una clase que contiene métodos estáticos para conversion entre Date y String, y
sacar directamente la fecha de hoy en ambos formatos:
class ConversionDeFechas {
// Hay que acomodar el fomato de la fecha, cambiandolo si se desea en las lineas de cada SimpleDateFormat
//******************************* dia de hoy en formato STRING

public class Pruebas {


public static String hoy_en_STRING() { public static void main(String[] args) {
Calendar cc = Calendar.getInstance(); // dia de hoy en formato STRING
String hoy = ConversionDeFechas.hoy_en_STRING();
Date hoyEnDate = cc.getTime(); System.out.println(hoy);
Iñaki Martín

SimpleDateFormat miFormato = new SimpleDateFormat("dd/MM/yyyy");


// dia de hoy en formato DATE
String fechaEnString = miFormato.format(hoyEnDate); Date dateDeHoy = ConversionDeFechas.hoy_en_DATE();
return fechaEnString; System.out.println(dateDeHoy);
} // si tengo un objeto String, pasarlo a DATE
String dia = "12/02/2014";
Date diaEnDate = ConversionDeFechas.de_STRING_a_DATE(dia);
//******************************* dia de hoy en formato DATE de java.util System.out.println(diaEnDate);
public static Date hoy_en_DATE() {
// si tengo un objeto DATE, pasarlo a String
Calendar cc = Calendar.getInstance(); String undia = ConversionDeFechas.de_DATE_a_STRING(diaEnDate);
java.util.Date hoyEnDate = cc.getTime(); System.out.println(undia);
}
return hoyEnDate;
©

}
}

//******************************* convertir de un STRING a un Date de java.util


public static Date de_STRING_a_DATE(String fechaEnString) {
Temario de curso JavaSE

SimpleDateFormat miFormato2 = new SimpleDateFormat("dd/MM/yyyy");


Date fechaenjava = null;
try { fechaenjava = miFormato2.parse(fechaEnString); }
catch (ParseException e) { e.printStackTrace(); }
return fechaenjava;
}

//******************************* convertir de un Date de java.util a STRING


public static String de_DATE_a_STRING(Date fechaEnDate) {
// la fecha en String ha de tener el formato que se indica en la linea siguiente:
SimpleDateFormat miFormato = new SimpleDateFormat("dd/MM/yyyy");
String fechaEnString = miFormato.format(fechaEnDate);
return fechaEnString;
}

//******************************* Conseguir el String del dia de hoy para una query de MySql
//******************************* Devuelve un String del tipo "STR_TO_DATE('11/12/2016','%d/%m/%Y')"
public static String hoy_en_STRING_PARA_MYSQL() {
Calendar cc = Calendar.getInstance();
Date hoyEnDate = cc.getTime();
SimpleDateFormat miFormato = new SimpleDateFormat("dd/MM/yyyy");
String hoyEnString = miFormato.format(hoyEnDate);
String hoyEnStringSql = "STR_TO_DATE('" + hoyEnString + "','%d/%m/%Y')";
return hoyEnStringSql;
}

}
10.- Clases complementarias Clases básicas tipo fecha (I) 14

Comparando fechas y diferencia entre ellas


• Para hacer comparaciones entre fechas, puede usarse:
a) los métodos before() y after(), junto con equals() (que va ya sobrescrito)
b) el metodo compareTo() (también sobrescrito para que funcione correctamente en modo fecha)

c) el metodo getTime(), que devolviendo un entero, puede compararse con operadores lógicos < , > e ==
Iñaki Martín

Calendar a1 = Calendar.getInstance();
Date f1 = a1.getTime();
Thread.sleep(10);
Calendar a2 = Calendar.getInstance();
Date f2 = a2.getTime();
/// TODAS ESTAS COMPARACIONES DAN TRUE
if (f1.before(f2)) { System.out.println("menor en 1"); }
©

if (f1.compareTo(f2) < 0) { System.out.println("menor en 2"); }


if (f1.getTime() < f2.getTime()) { System.out.println("menor en 3");}
if (a1.getTimeInMillis() < a2.getTimeInMillis()) { System.out.println("menor en 4");}
Temario de curso JavaSE

Calculando diferencia entre fechas


• Para calcular que tiempo ha pasado entre dos fechas, hay que hacerlo por programación. Esta puede ser una
solución;
final int MILISEGUNDOS_EN_UN_DIA = 1000 * 60 * 60 * 24;
try {
Date primfecha = new SimpleDateFormat ("dd/MM/yyyy").parse ("23/11/2023");
Date segunfecha = new SimpleDateFormat ("dd/MM/yyyy").parse ("21/12/2023");
long ddias = (primfecha.getTime () - segunfecha.getTime ()) / MILISEGUNDOS_EN_UN_DIA;
System.out.println ("Entre " + segunfecha + " y " + primfecha + " hay " + ddias + " dias ");
}
catch (ParseException e) {e.printStackTrace ();}

• Este ejemplo anterior vale para calcular un numero global de días, y podría valer igual para meses o años, pero
no para una combinación de ellos. Esto exige un método más elaborado, que queda entre los ejercicios
propuestos de este capítulo
10.- Clases complementarias Fechas y String, formateo 15

Formateo con SimpleDateFormat Formateo de Date con printf()


• Cuidado al usar caracteres en el formato al aplicar • Cuando se usa printf() para dar formato a un
SimpleDateFormat. objeto fecha, se pueden usar 2 caracteres para
• MM representa el mes, pues mm son minutos. sacar un dato de la fecha. El primero es una “t”,

• La tabla siguiente tiene una tabla completa con los seguida de algún calificador.
• La tabla siguiente tiene una tabla con los
Iñaki Martín

caracteres a usar en formato:


principales calificadores:
Simbolo Significado Calificador Significado Ejemplo
Mon May 04 09:51:52 CDT 2009
y Año c Fecha completa
M Mes F Fecha formato ISO 8601 2004-02-09
d Dia del mes D Fecha formato U.S. (mes/dia/año) 02/09/2004
©

h Hora de tipo (1-12, AM/PM) T hora en formato 24-horas 18:05:19


H Hora de tipo (0-23) r hora en formato 12-horas 06:05:19 pm
k Hora de tipo (1-24)
Temario de curso JavaSE

R hora en formato 24-horas, sin 18:05


m Minuto
Y Añossegundos
con 4 dígitos 2004
s Segundo
E Dia en la semana y Años con 2 dígitos 04
D Dia en el año (1-365 or 1-364) C Primeros dos dígitos del año 20
w Semana del año (1-53) B Mes entero February
W Semana en el mes(1-5) b Mes abreviado Feb
a AM/PM m Mes con dos dígitos 2
d Dia con dos dígitos (ceros por delante) 03
// Usando SimpleDateFormat e Dia con dos dígitos (sin ceros delante) 9
SimpleDateFormat sw = new SimpleDateFormat ("hh-mm dd/MM"); A Dia semana entero Monday
// Usando prinf() a Dia semana abreviado Mon
Date f1 = new Date ();
System.out.printf ("\n Mes: %tB ", f1); H Hora con dos dígitos entre 00 y 23 18
System.out.printf ("\n Hora: %tH - %tM ", f1, f1); I Hora con dos dígitos entre 01 y 12 6
M Minutos con dos dígitos 5
S Segundos con dos dígitos 19
p Marcador am / pm pm
10.- Clases complementarias Enumerados (I) 16

Enumerados
๏ Un enumerado (o Enum) es una clase “especial” que permite crear un nuevo tipo de datos, pero cuyos
posibles valores están limitados a los definidos en la clase
๏ Solo existen desde la versión JSE 5. Antes de esta versión, para definir un valor específico solo podían usarse

las constantes, pero se podía agruparlas bajo un mismo “concepto”


Iñaki Martín

final int HOMBRE=1, MUJER=2;

๏ Además de no poder “agruparse”, tampoco podían controlarse su uso. Nada impedía la segunda linea:
int sexo1 = HOMBRE; // hasta aquí vale, un valor controlado
©

int sexo2 = 32; // este ya no es un valor controlado !!

๏ Por eso se crearon los enumerados, tipos de datos con nombre común (el tipo de dato a crear) y valores
Temario de curso JavaSE

limitados (el conjunto de valores que puede tomar el tipo)


๏ Un enumerado se declara asi:
// <delimitador> enum TipoDeDatoACrear {VALOR1, VALOR2,..};

// definicion de algunos enumerado simples, solo con valores


public enum Sexo { HOMBRE, MUJER }
public enum EstadoCivil { CASADO, SOLTERO, DIVORCIADO }
public enum Bulean { VERDADERO, FALSO }

๏ Esta declaración puede estar


1. Fuera de cualquier clase, como una clase independiente (lo que de hecho es)
2. Dentro de una clase, pero NO dentro de un método
10.- Clases complementarias Enumerados (II) 17

Objetos enumerados
• Un enumerado se trata como una clase más, con lo que para usar los valores de este tipo de dato:
1. Se pueden consultar directamente como clase.valor System.out.println (Sexo.HOMBRE);

2. Se pueden crear objetos de la clase, y darles valor :


System.out.println (Sexo.HOMBRE); // Se puede CONSULTAR un valor de un enumerado
Iñaki Martín

Sexo h = Sexo.HOMBRE; // Se puede definir una variable del tipo enumerado y darle un valor
Sexo m = Sexo.MUJER;
// Se puede definir una variable del tipo enumerado y darle un valor
System.out.println (h); // y luego consultarlo...
sexo h = sexo.HOMBRE;
if(h==m){ sexo m = sexo.MUJER;
// o compararlo... con equals o con ==
System.out.println
System.out.println ("Son(h);
del mismo sexo");
}
©

• Todos los enumerados disponen de varios métodos propios (todos heredan de la clase java.lang.Enum).
Este ejemplo muestra algunos de dichos métodos:
Temario de curso JavaSE

/* — Ejemplo de ejecución
HOMBRE
HOMBRE
Sexo h = Sexo.HOMBRE; HOMBRE
Sexo m = Sexo.MUJER; 0
-1
System.out.println( h.toString() ); // escribe el valor enumerado como String: HOMBRE */
System.out.println( h ); // esto como si se ejecuta el toString()
System.out.println( h.name() ); // esto tambien da un String con el valor, por si se cambia toString()
System.out.println( h.ordinal() ); // esto da el ordinal del valor enumerado en la lista enumerada: 0
System.out.println( h.compareTo(m) ); // devuelve boolean en la comparacion, según el orden en que están declarados

• Se pueden recorrer todos los enumerados de una clase enumerada con un for-each, pues todas las
enumeraciones disponen del método estático values(), que devuelve un array con todos los objetos de la
clase: /* — Ejemplo de ejecución
HOMBRE
// Se puede recorrer todos los valores de la enumeración con un for-each MUJER
*/
for (Sexo d : Sexo.values ()) {
System.out.println (d.toString());
}
10.- Clases complementarias Enumerados (III) 18

• Es muy importante tener claro que los enumerados no son Strings (aunque pueden serlo), sino que son objetos de
una clase. Es un error habitual creer que un enumerado es una lista finita de Strings, y no lo es asi, son una lista finita
de objetos de una determinada clase con sus atributos, constructor y métodos.

int k = Sexo.HOMBRE; // ERROR: un valor de un enumerado no es un int


String f = Sexo.HOMBRE; // ERROR: un valor de un enumerado no es un String
Iñaki Martín

• A diferencia de los objetos de las clases estándar, los objetos enumerados pueden ser utilizados en expresiones
de comparación de igualdad mediante el signo == (o con el metodo .equals() ) y como valores de una
instrucción switch:
©

Sexo h = Sexo.HOMBRE;
Sexo m = Sexo.MUJER;
if(h==m){ // comparar con equals o con ==
System.out.println ("Son del mismo sexo");
Temario de curso JavaSE

Más cosas sobre enumerados

• Un enumerado creado fuera de una clase no puede ser declarado static, final, protected ni private, solo public.
• Aunque se puede usar simplemente como un enumeración de valores, en realidad es una clase (casi) normal, con lo que:
1. Los valores de la clase enumerada se crean al invocar a algún valor de la clase, o al crear un objeto, se hace de modo
Temas avanzados

automático (implícito) con la simple invocación o creación del objeto.


2. Una clase enumerada puede tener atributos, más alla de los propios valores enumerados
3. Una clase enumerada puede tener métodos como cualquier clase normal (p.e. getters/setters de sus atributos)
4. Una clase enumerada puede tener constructores. En este caso, deben ser private con lo que no se puede usar new
para crear nuevos objetos (valores) desde fuera de la clase. Al tener que ser private forzosamente, no es necesario
declararlos explícitamente private. En el apartado siguiente se explica el uso de constructores en enumerados, dado
que es un poco confuso
10.- Clases complementarias Constructor de enumerados 19

Constructores de enumerados
• Una clase enumerada puede tener constructores, aunque su uso es un poco confuso
• En los constructores se puede usar parámetros, que afecten o no a la inicialización de algún atributo de la clase.
• Si afectan a la inicialización de atributos, hay que entender que los atributos realmente deben estar asociados a cada valor posible de la
enumeración, Si se usan así, los valores de la enumearacion deben tener también los valores de sus propios atributos.

• Ejemplo: creo un enumerado ProvinciasExtremadura con dos valores (CACERES y BADAJOZ),


• Luego defino más atributos, prefijoTelefonico y prefijoPostal. Y deseo que esos variables sean atributos de cada valor del enumerado (esto es,
Iñaki Martín

que CACERES tenga su prefijoTelefonico y prefijoPostal, y BADAJOZ los suyos)


• Para ello, hago dos cosas:
1. Creo un constructor que recibe dos parámetros, un String y un int (para prefijoPostal y prefijoTelefónico respectivamente)
2. En la definición de los valores , añado entre paréntesis los valores que deseo para cada atributo, en el orden dado en el constructor,
CACERES(“10”,927) BADAJOZ ("06", 924);
• Recordar que nuestros programas no hacen una invocación new, no hacen una llamada EXPLICITA al constructor. El constructor de un
©

enumerado ejecuta la primera vez que se crea un objeto de la clase enum, no antes, y solo UNA VEZ, y además , es donde da valor a TODOS
los miembros de la clase, y a sus atributos.
Temas avanzados

• El ejemplo completo esta en la página siguiente, pero podemos aquí analizar paso a paso lo ocurre en lo que respecta al constructor del
Temario de curso JavaSE

enumerado.
1. La primera vez que se hace referencia al enumerado ProvinciasExtremadura es en la linea
2. ProvinciasExtremadura pro1 = ProvinciasExtremadura.CACERES ; ;;
3. En este momento, se hace una llamada interna al constructor del enumerado
4. Construye el primer valor de la clase, CACERES
5. Como el constructor tiene parámetros, coge el primer valor de los declarados junto al valor CACERES (el “10”), y lo asocia al
parámetro pp. Y dentro del constructor, lo asigna al atributo prefijoPostal. Repite la operación con el segundo parámetro, asignando a
prefijoPostal el valor 927.
6. Repite los pasos 4 y 5 con el segundo valor del enumerado, BADAJOZ
• Hasta aquí la ejecución del constructor. Tras todo ello, el valor “10” a pasado a ser el valor del atributo prefijoPostal del valor enumerado
CACERES, de modo que después se puede invocar a dicho atributo perfectamente:
• ProvinciasExtremadura pro1 = ProvinciasExtremadura.CACERES; ;
System.out.println (pro1.prefijoPostal);
• Recordar que la ejecución del constructor es interna, no se controla por el usuario.
• Además de dar valor a atributos, el constructor puede hacer otras operaciones o recibir más parámetros, como si fuera un constructor normal
• Si no hay un constructor escrito, llama al constructor por defecto, que al no tener parámetros, solo crea valores y nada mas.
10.- Clases complementarias Constructor de enumerados 20

Constructor de enumerados (ejemplo)


public class PruebaEnum {
public enum ProvinciasExtremadura { // definicion de un enumerado con atributos, constructor y getter

// Lo primero que ha de tener el enumerado siempre es la declaracion de sus miembros. /* — Ejemplo de ejecución
// En este caso es una llamada al constructor que hay mas adelante,

este mensaje sale antes de construir


// pues asi se asigna valor a los atributos de cada elemento enumerado los valores del enumerado
CACERES("10", 927), BADAJOZ("06", 924); no hago nada, sirvo solo de ejemplo
Iñaki Martín

no hago nada, sirvo solo de ejemplo


// Aqui estan los atributos de cada enumerado, el orden no importa. no hago nada, sirvo solo de ejemplo
// Pueden tener valores prefijados o constantes y ser public o private.... o protected no hago nada, sirvo solo de ejemplo
int prefijoTelefonico; España
private String prefijoPostal; 06
protected String nacion = "España"; 9999
final int codInternacional = 34; */

// Este es el constructor que se usa para crear los elementos del enumerado
// Es PRIVATE pues solo se puede usar dentro de la propia clase enum
©

// Se puede usar como un constructor normal, con más codigo que la asignacion de atributos.
// Este constructor se ejecuta (y da valor a TODOS los miembros de la clase) la primera vez que se crea un objeto de la
// clase enum, no antes, y solo UNA VEZ
Temas avanzados

private ProvinciasExtremadura(String pp, int pt) {


this.prefijoPostal = pp;
Temario de curso JavaSE

this.prefijoTelefonico = pt;
for (int i = 0; i < 2; i++)
System.out.println("no hago nada, sirvo solo de ejemplo");
}

// si hay atributos privados, necesito getters para ellos


public String getPrefijoPostal() {
return prefijoPostal;
}

// y tambien puedo usar setters para cambiar sus atributos !!


public void setPrefijoPostal(String prefijoPostal) {
this.prefijoPostal = prefijoPostal;
}
}

public static void main(String[] args) {


System.out.println("este mensaje sale antes de construir los valores del enumerado");
ProvinciasExtremadura pro1 = ProvinciasExtremadura.CACERES;
ProvinciasExtremadura pro2 = ProvinciasExtremadura.BADAJOZ;
System.out.println(pro1.nacion); // a este atributo accedo direto por que es publico
System.out.println(pro2.prefijoPostal); // y a este atributo le cambio el valor con un setter
pro2.setPrefijoPostal(“9999"); // a este atributo accedo direto por que es publico
System.out.println(pro2.prefijoPostal);
}
}
10.- Clases complementarias Métodos para algunos trucos 21

Como suspender la ejecución de un programa


• Si nos encontramos en la necesidad de tener que suspender durante un tiempo dado la ejecución del
programa, se puede usar el método sleep() de la clase Thread, método que es estático, por lo que se puede
invocar con el nombre de la clase. El parámetro de sleep son los milisegundos que se para la ejecución, por lo

que este ejemplo suspende durante 4 segundos


Iñaki Martín

try {
System.out.println("Fecha y hora actual" + new Date());
Thread.sleep(4000);
System.out.println("Fecha y hora actual" + new Date());
} catch (Exception e) { e.printStackTrace(); }}
©

Medir el tiempo de ejecución de un programa


Temario de curso JavaSE

• Si necesitamos medir un intervalo de tiempo entre dos puntos del protrama, podemos usar
System.currentTimeMillis(), que devuelve un long, que representa la hora actual en milisegundos, y comparar
dos ejecuciones separadas de este método. Por ejemplo:

try {
long puntoInicio = System.currentTimeMillis();
System.out.println("Fecha y hora actual" + new Date());
Thread.sleep(3000);
System.out.println("Fecha y hora actual" + new Date());
long puntoFin = System.currentTimeMillis();
long dif = puntoFin - puntoInicio;
System.out.println("La diferencia de tiempo ha sido: "+dif/1000+" segundos");
} catch (Exception e) { e.printStackTrace(); }

También podría gustarte