Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
- Clases complementarias
TEMARIO DE CURSO
PROGRAMACIÓN JAVA SE
Iñaki Martín
CAPÍTULO 10
CLASES COMPLEMENTARIAS
©
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 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.
©
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
๏ 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
๏ 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?
๏ 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
• 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 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
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
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
©
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
• 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
• 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
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
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
Calendar cc = Calendar.getInstance();
Date d2 = cc.getTime();
Calendar c2 = new GregorianCalendar();
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();
©
System.out.println(fechaEnTexto);
String fechaEnTexto2 = new SimpleDateFormat("dd/MM/yyyy").format(fecha); // en una sola linea
๏ 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
}
}
//******************************* 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
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"); }
©
• 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
• 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
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
๏ 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
©
๏ 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
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);
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.
• 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
• 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
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.
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
// 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 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
this.prefijoTelefonico = pt;
for (int i = 0; i < 2; i++)
System.out.println("no hago nada, sirvo solo de ejemplo");
}
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(); }}
©
• 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(); }