[icono]Manual de Java Volver a índice

Capítulo 9. Utilidades.


La biblioteca de clases de Java contiene un conjunto de clases de utilidades utilizadas en todos los paquetes principales de Java. Estas clases están almacenadas en los paquetes java.lang y java.util. Se utilizan para almacenar conjuntos de objetos, realizar la interfaz con funciones del sistema de bajo nivel, funciones matemática, generación de números aleatorios y manipulación de fecha/hora.

Envolturas de tipo simple

Como ya sabemos, Java utiliza tipos primitivos como int y char por razones de rendimiento. A veces, se necesitará crear una representación como objeto de uno de estos tipos simples, por lo que Java proporciona clases para cada uno de estos tipos simples.

Number

La clase abstracta Number representa una interfaz a todos los tipos escalares estándar: long, int, float y double. Number tiene métodos de acceso que devuelven el valor posiblemente redondeado del objeto de cada uno de los objetos simples:

Double y Float

Double y Float son subclases de Number. Ambas clases tienen dos constructores para inicializarlas con valores double y float, o, lo que es muy práctico, se pueden inicializar con una representación tipo String del valor:

Double d1 = new Double(3.14159);
Double d2 = new Double("314159E-5");

Integer y Long

La clase Integer es una envoltura alrededor de int, short y byte. Long es una envoltura alrededor del tipo long. Además de los métodos heredados de Number tienen otros muy útiles:

Character

Character es una envoltura simple alrededor de un char. Tiene varios métodos útiles static, que se pueden utilizar para probar varias condiciones de un carácter:

Boolean

Boolean es un envoltorio muy fino alrededor de valores boolean, que solo es útil para situaciones de paso por referencia.

Enumeraciones

Java tiene matrices para almacenar grupos de datos de tipo similar, que son muy útiles para modelos simples de acceso a datos. Sin embargo, las enumeraciones ofrecen una manera más completa y orientada a objetos para almacenar conjuntos de datos de tipo similar. Las enumeraciones tienen su propia asignación de memoria y posibilidad de una nueva asignación para ampliarlas. Tienen interfaces de método para su iteración y recorrido. Se pueden indexar mediante algo más complejo y útil que los simples enteros.

Interfaz de enumeración

Enumeration es una interfaz simple que permite enumerar todos los elementos de cualquier conjunto de objetos. Especifica dos métodos. El primero, un método boolean llamado hasMoreElements, devuelve true cuando todavía quedan más elementos que extraer. El segundo, nextElement devuelve una referencia a objeto genérica cuyo tipo hay que convertir al tipo de clase de la cual el objeto es una instancia.

Vector

Un Vector es una matriz ampliable de referencias a objeto. Internamente, un Vector implementa una estrategia de crecimiento para minimizar la reasignación y el espacio desperdiciado. Los objetos se pueden almacenar al final de un Vector utilizando el método addElement o en un índice dado mediante el método insertElement. Se puede almacenar una matriz en un Vector utilizando el método copyInto. Una ves se ha almacenado un conjunto de objetos en un Vector, se puede utilizar para buscar un elemento en concreto utilizando los métodos contains, indexOf, o lastIndexOf. También se puede extraer un objeto de una posición específica de un Vector utilizando los métodos elementAt, firstElement y lastElement.

Stack

Una Stack es una subclase de Vector que implementa una pila simple del tipo FIFO. Además de los métodos de Vector estándares, Stack implementa push que coloca objetos en la parte superior de la pila y pop que retira y devuelve el objeto superior de la pila. También se puede utilizar peek para obtener el objeto superior de la pila, pero no retirarlo. El método empty devolverá true si no hay nada en la pila. El método search comprobará si existe un objeto en la pila y devuelve el número de pops que se necesitarán para que dicho objeto quede en la parte superior de la pila o -1 si el objeto pasado como parámetro no se encuentra.

Dictionary

Un Dictionary es una clase abstracta que representa un depósito para almacenar claves/valores. Una clave es un nombre que se utiliza para recuperar un valor más adelante. Dada una clave y un valor, se puede almacenar el valor en un Dictionary con el método put(clave, valor). Después se puede utilizar get(clave) para recuperar. Se pueden devolver las claves y valores como una enumeration utilizando los métodos keys y elements. El método size devuelve el número de parejas clave/valor almacenadas en un diccionario e isEmpty devuelve true cuando no queda ninguna pareja. Se puede utilizar el método remove(clave) para eliminar una pareja clave/valor.

Hashtable

Una Hashtable es una implementación concreta de un Dictionary. Se puede utilizar una instancia de Hashtable para almacenar objetos arbitrarios que están indexados por cualquier otro objeto arbitrario. La utilización mas habitual de una Hashtable es utilizar una String como clave para almacenar objetos como valores. El ejemplo siguiente crea una Hashtable para almacenar información acerca de este libro:

import java.util.Dictionary;
import java.util.Hashtable;

class HTDemo {
   	public static void main(String args[]) {
		Hashtable ht = new Hashtable();
		ht.put("title", "Manual de Java");
		ht.put("author", "Algunos");
		ht.put("email", "nisesabe@puesalli.es");
		show(ht);
	}
	    static void show(Dictionary d)  {
		System.out.println("Título: " + d.get("title");
		System.out.println("Autor: " + d.get("author");
		System.out.println("E-mail: " + d.get("email");
	}
}

La salida de este programa muestra cómo el método show, que toma un Dictionay abstracto como parámetro, es capaz de recuperar todos los valores que se han almacenado en el método main.

Properties

Properties en una subclase de Hashtable que añade algunos métodos adecuados para obtener valores que puede que no estén definidos. Se puede especificar un valor por omisión junto con el nombre en el método getProperty; por ejemplo, getProperty("nombre","valor por omisión"). Si no se encuentra la propiedad "nombre", se devuelve "valor por omisión". Además, cuando se construye un objeto Properties, se le puede pasar otra instancia de Properties en el constructor para que se utilice como propiedades por omisión de la nueva instancia.

Runtime

La clave Runtime encapsula el proceso del intérprete de Java que se ejecuta. No se puede crear una instancia de Runtime; sin embargo, se puede obtener una referencia al objeto Runtime que se está ejecutando actualmente llamando la método estático Runtime.getRuntime. Una vez tenga el descriptor del proceso en ejecución, puede llamar a varios métodos que controlan el estado y comportamiento de la máquina virtual de Java.

Gestión de memoria

Aunque Java es un sistema de recogida de "basura" automática, se podría desear el conocer el tamaño del montículo de objetos y su espacio libre para comprobar la eficiencia de su código. Utilizar los métodos totalMemory y freeMemory de Runtime para obtener esa información.

System

La clase System contiene un conjunto curiosos de funciones y variables globales. Vamos a ver algunas de las más útiles aquí. La entrada y salida estándar del interprete de Java se almacena en las variables in y out. Hemos estado utilizando System.out.println() en la mayoría de los ejemplos de este libro.

El método currentTimeMillis devuelve la hora actual en milisegundos desde el 1 de enero de 1970. Habitualmente es un número muy grande. Se puede utilizar este long para inicializar un objeto Date, como ya veremos. El método arraycopy se puede utilizar para copiar rápidamente una matriz de cualquier tipo desde un sitio a otro. Es mucho más rápido que el bucle equivalente escrito en Java.

Propiedades del entorno

El intérprete de Java muestra las variables de entorno a través de una instancia de Properties, cuyo descriptor se puede obtener llamando al método System.getProperties. System.getProperties es una función adecuada que llama a getProperty sobre este objeto Properties de entorno.

Date

La clase Date se utiliza para presentar una fecha y una hora. Se pueden manipular el día, mes, año, día de la semana, horas, minutos y segundos. Hay varios constructores para objetos Date. El más simple, Date(), inicializa el objeto con la fecha y hora actual. Hay tres constructores más que ofrecen niveles de especificidad mayores para la precisión que se desea para la hora:

Get y Set

Date incluye un conjunto de métodos para obtener (get) y establecer (set) el año, mes, día, hora, minuto y segundo de una instancia. Sólo se puede obtener el día de la semana, ya que está relacionado con el día del mes. Cada una de las funciones get -getYear, getMonth, getDate, getDay, getHours, getMinutes y getSeconds- devuelve un int. Cada uno de los métodos set -setYear, setMonth, setDate, setHours, setMinutes y setSeconds- toma un parámetro int.
Se puede obtener la representación long de un objeto Date con el método getTime. Es el número en milisegundos desde el 1 de enero de 1970.

Comparación

Si se tienen dos objetos Date que se desean comparar, se podrían convertir a su representación como long para compararlos como números enteros en milisegundos. La clase Date incluye tres métodos que se pueden utilizar para una comparación directa: before, after y equals. Por ejemplo, new Date(96, 11, 10).before(new Date(96, 11, 7)) devuelve true, porque el 10 es anterior al 7.

Math

La clase Math contiene todas las funciones en coma flotante que se utilizan en geometría y trigonometría. Hay dos constantes double que se utilizan en este tipo de cálculos, E (aproximadamente 2.72) y PI (aproximadamente 3.14).

Transcendentes

Las tres funciones siguientes aceptan un parámetro double para un ángulo en radianes y devuelven el resultado de su respectiva función trascendente:

Estas funciones aceptan un parámetro double que es el resultado de una función trascendente y devuelven el ángulo en radianes que produciría ese resultado. En cierto modo como Jeopardy, el conjunto de funciones siguiente es la inversa de sus correspondientes sin "a":

Exponenciales

Redondeo

Hay versiones con múltiples formas de los métodos abs, min y max para int, long. float y double:

Random

La clase Random es un generador de números pseudo- aleatorios. Se les llama números pseudo-aleatorios porque son secuencias distribuidas uniformemente obtenidas a partir de una semilla inicial. Cuando se inicializa un objeto Random con una semilla, se puede obtener a continuación lo que parece una secuencia aleatoria. Pero, si se vuelve a utilizar la misma semilla para inicializar otro objeto Random, se obtendrá la misma secuencia. Habitualmente, se utiliza la hora actual como semilla de un objeto Random, lo que disminuye la posibilidad de obtener secuencias de números repetidas. Hay cinco tipos de números aleatorios que se pueden extraer de un objeto Random. Se puede extraer un int, distribuido uniformemente a lo largo del rango de int, mediante el método nextInt. Del mismo modo, se puede obtener un long mediante nextLong. Los métodos nexFloat y nextDouble devuelven un float y double respectivamente distribuidos uniformemente entre 0.0 y1.0. Por último, nextGaussian devuelve un double de distribución gaussiana centrada en 0.0 con una desviación típica de 1.0. A esta distribución se le llama curva tipo campana.