Está en la página 1de 10

3.10 Definición, creación y reutilización de paquetes/librerías.

Las clases que Sun ha creado están almacenadas en librerías de clases llamadas
"paquetes". Para que una clase de un paquete esté disponible en su código, tiene que
importar el paquete, lo que quiere decir que el compilador localizará ese paquete para
esas clases. Además puede importar clases individuales que no son parte de un
paquete.

Por defecto, sólo las sentencias básicas de Java están disponibles en una aplicación,
las del paquete java.lang. El compilador automáticamente importa el paquete java.lang,
pero para usar el resto de las clases que vienen con Java tendrá que hacer la
importación con la instrucción import.

Aquí se muestra cómo utilizar esa sentencia:

import [paquetel[.paquete2 ... ].]-(nombre de clase[*);

Observe que se pone un punto ('.') entre el paquete y los nombres de clase para
separarlos. Los paquetes Java estándares están almacenados en un gran paquete
llamado java, por lo que el paquete de utilidades se llama realmente java.uti1 (hay otros
grandes paquetes disponibles; por ejemplo, el paquete swing está almacenado en el
paquete java).

Puede referirse a la clase Date en java.uti1 como java.util.Date. A continuación se


indica cómo importar esa clase en un programa:

import java.util.Date;
public class app

Observe que si va a usar las sentencias import para importar clases en un programa,
éstas deberían estar en la parte de arriba del código. Así, podemosutilizar la clase Date,
como se indica a continuación (observe que estamoscreando un objeto de la clase Date
usado el operador Java new.

import java.util.Date;
public class app
I
public static void main(String[] args)
System.out.println("Hoy = " + new Date());

Cuando ejecute esta aplicación, verá la fecha del día:


c:\>java app
HOY = Lunes 2 Agosto 12:15:13 EDT 2000

Como puede ver estudiando la forma general de la sentencia previa import, hay también
una técnica taquigráfica que carga todas las clases de un paquete; se puede usar un
asterisco ('*') para utilizar todas las clases de un paquete específico. A continuación se
indica cómo se podría hacer si quisiera importar todas las clases del paquete java.uti1
de una vez:
public class app
{
public static void main(String[] args)
{
System.out.println("Hoy = " + new Date());
}
}

Qué es un package
Un package es una agrupación de clases. En la API de Java 1.1 había 22 packages;
en Java 1.2 hay 59 packages, lo que da una idea del “crecimiento” experimentado por
el lenguaje. Además, el usuario puede crear sus propios packages.

Para que una clase pase a formar parte de un package llamado pkgName, hay que
introducir en ella la sentencia:
package pkgName;
que debe ser la primera sentencia del fichero sin contar comentarios y líneas en blanco.

Los nombres de los packages se suelen escribir con minúsculas, para distinguirlos de
las clases, que empiezan por mayúscula. El nombre de un package puede constar de
varios nombres unidos por puntos (los propios packages de Java siguen esta norma,
como por ejemplo java.awt.event).

Todas las clases que forman parte de un package deben estar en el mismo directorio.
Los nombres compuestos de los packages están relacionados con la jerarquía de
directorios en que se guardan las clases.

3.9 Clases Predefinidas.

CLASES STRING Y STRINGBUFFER

Las clases String y StringBuffer están orientadas a manejar cadenas de caracteres.


La clase String está orientada a manejar cadenas de caracteres constantes, es decir,
que no pueden cambiar. La clase StringBuffer permite que el programador cambie la
cadena insertando, borrando, etc. La primera es más eficiente, mientras que la segunda
permite más posibilidades.

Ambas clases pertenecen al package java.lang, y por lo tanto no hay que importarlas.
Hay que indicar que el operador de concatenación (+) entre objetos de tipo String
utiliza internamente objetos de la clase StringBuffer y el método append().

Los métodos de String se pueden utilizar directamente sobre literals (cadenas entre
comillas), como por ejemplo: "Hola".length().
Métodos de la clase String

Los objetos de la clase String se pueden crear a partir de cadenas constantes o literals,
definidas entre dobles comillas, como por ejemplo: "Hola". Java crea siempre un objeto
String al encontrar una cadena entre comillas. A continuación se describen dos formas
de crear objetos de la clase String,

String str1 = "Hola"; // el sistema más eficaz de crear Strings


String str2 = new String("Hola"); // también se pueden crear con un constructor

El primero de los métodos expuestos es el más eficiente, porque como al encontrar un


texto entre comillas se crea automáticamente un objeto String, en la práctica utilizando
new se llama al constructor dos veces. También se pueden crear objetos de la clase
String llamando a otros constructores de la clase, a partir de objetos StringBuffer, y de
arrays de bytes o de chars.

La siguiente Tabla muestra los métodos más importantes de la clase String.

Métodos de String Función que realizan

String(...) Constructores para crear Strings a partir de arrays de


bytes o de caracteres
String(String str) y Costructores a partir de un objeto String o StringBuffer
String(StringBuffer sb)
charAt(int) Devuelve el carácter en la posición especificada

getChars(int, int, char[], int) Copia los caracteres indicados en la posición indicada
de un array de caracteres
indexOf(String, [int]) Devuelve la posición en la que aparece por primera vez
un String en otro String, a partir de una posición dada
(opcional)
lastIndexOf(String, [int]) Devuelve la última vez que un String aparece en otro
empezando en una posición y hacia el principio

length() Devuelve el número de caracteres de la cadena


replace(char, char) Sustituye un carácter por otro en un String
startsWith(String) Indica si un String comienza con otro String o no
substring(int, int) Devuelve un String extraído de otro
toLowerCase() Convierte en minúsculas (puede tener en cuenta el
locale)
toUpperCase() Convierte en mayúsculas (puede tener en cuenta el
locale)
trim() Elimina los espacios en blanco al comienzo y final de la
cadena
valueOf() Devuelve la representación como String de sus
argumento. Admite Object, arrays de caracteres y los
tipos primitivos
Tabla Algunos métodos de la clase String.
Un punto importante a tener en cuenta es que hay métodos, tales como
System.out.println(), que exigen que su argumento sea un objeto de la clase String.
Si no lo es, habrá que utilizar algún metodo que lo convierta en String.

CLASE MATH

La clase java.lang.Math deriva de Object. La clase Math proporciona métodos static


para realizar las operaciones matemáticas más habituales. Proporciona además las
constantes E y PI, cuyo significado no requiere muchas explicaciones.

La siguiente Tabla muestra los métodos matemáticos soportados por esta clase.

Métodos Significado Métodos Significado


abs() Valor absoluto sin(double) Calcula el seno
acos() Arcocoseno tan(double) Calcula la tangente
asin() Arcoseno exp() Calcula la función
exponencial
atan() Arcotangente entre -PI/2 log() Calcula el logaritmo
y PI/2 natural (base e)
atan2( , ) Arcotangente entre -PI y max( , ) Máximo de dos
PI argumentos
ceil() Entero más cercano en min( , ) Mínimo de dos
dirección a infinito argumentos

floor() Entero más cercano en random() Número aleatorio entre


dirección a -infinito 0.0 y 1.0

round() Entero más cercano al power( , ) Devuelve el primer


argumento argumento elevado al
segundo
rint(double) Devuelve el entero más sqrt() Devuelve la raíz
próximo cuadrada
IEEEremainder( Calcula el resto de la toDegrees(dou Pasa de radianes a
double,double) división ble) grados (Java 2)
cos(double) Calcula el coseno toRadians() Pasa de grados a
radianes (Java 2)
Tabla. Métodos matemáticos de la clase Math
.

Manejo de Excepciones.
EXCEPCIONES
A diferencia de otros lenguajes de programación orientados a objetos como C/C++,
Java incorpora en el propio lenguaje la gestión de errores. El mejor momento para
detectar los errores es durante la compilación. Sin embargo prácticamente sólo los
errores de sintaxis son detectados durante este periodo El resto de problemas surgen
durante la ejecución de los programas.
En el lenguaje Java, una Exception es un cierto tipo de error o una condición anormal
que se ha producido durante la ejecución de un programa. Algunas excepciones son
fatales y provocan que se deba finalizar la ejecución del programa. En este caso
conviene terminar ordenadamente y dar un mensaje explicando el tipo de error que se
ha producido.

Un buen programa debe gestionar correctamente todas o la mayor parte de los errores
que se pueden producir. Hay dos “estilos” de hacer esto:

1. A la “antigua usanza”: los métodos devuelven un código de error. Este código se


chequea en el entorno que ha llamado al método con una serie de if elseif …,
gestionando de forma diferente el resultado correcto o cada uno de los posibles errores.
Este sistema resulta muy complicado cuando hay varios niveles de llamadas a los
métodos.
2. Con soporte en el propio lenguaje: En este caso el propio lenguaje proporciona
construcciones especiales para gestionar los errores o Exceptions. Suele ser lo
habitual en lenguajes modernos, como C++, Visual Basic y Java.
En los siguientes apartados se examina cómo se trabaja con los bloques y expresiones
try, catch, throw, throws y finally, cuándo se deben lanzar excepciones, cuándo se
deben capturar y cómo se crean las clases propias de tipo Exception.

EXCEPCIONES ESTÁNDAR DE JAVA

Los errores se representan mediante dos tipos de clases derivadas de la clase


Throwable: Error y Exception. La siguiente figura muestra parcialmente la jerarquía de
clases relacionada con Throwable:
La clase Error está relacionada con errores de compilación, del sistema o de la JVM.
De ordinario estos errores son irrecuperables y no dependen del programador ni debe
preocuparse de capturarlos y tratarlos.

La clase Exception tiene más interés. Dentro de ella se puede distinguir:

1. RuntimeException: Son excepciones muy frecuentes, de ordinario relacionadas


con errores de programación. Se pueden llamar excepciones implícitas.

2. Las demás clases derivadas de Exception son excepciones explícitas. Java


obliga a tenerlas en cuenta y chequear si se producen.

El caso de RuntimeException es un poco especial. El propio Java durante la ejecución


de un programa chequea y lanza automáticamente las excepciones que derivan de
RuntimeException. El programador no necesita establecer los bloques try/catch para
controlar este tipo de excepciones.

Representan dos casos de errores de programación:


1. Un error que normalmente no suele ser chequeado por el programador, como por
ejemplo recibir una referencia null en un método.
2. Un error que el programador debería haber chequeado al escribir el código, como
sobrepasar el tamaño asignado de un array (genera un
ArrayIndexOutOfBoundsException automáticamente).

En realidad sería posible comprobar estos tipos de errores, pero el código se


complicaría excesivamente si se necesitara chequear continuamente todo tipo de
errores (que las referencias son distintas de null, que todos los argumentos de los
métodos son correctos, y un largo etcétera).

Las clases derivadas de Exception pueden pertenecer a distintos packages de Java.


Algunas pertenecen a java.lang (Throwable, Exception, RuntimeException, …); otras a
java.io (EOFException, FileNotFoundException, ...) o a otros packages. Por heredar de
Throwable todos los tipos de excepciones pueden usar los métodos siguientes:

1. String getMessage() Extrae el mensaje asociado con la excepción.


2. String toString() Devuelve un String que describe la excepción.
3. void printStackTrace() Indica el método donde se lanzó la excepción.

LANZAR UNA EXCEPTION


Cuando en un método se produce una situación anómala es necesario lanzar una
excepción. El proceso de lanzamiento de una excepción es el siguiente:

1. Se crea un objeto Exception de la clase adecuada.


2. Se lanza la excepción con la sentencia throw seguida del objeto Exception creado.

// Código que lanza la excepción MyException una vez detectado el error


MyException me = new MyException("MyException message");
throw me;
Esta excepción deberá ser capturada (catch) y gestionada en el propio método o en
algún otro lugar del programa (en otro método anterior en la pila o stack de llamadas).

Al lanzar una excepción el método termina de inmediato, sin devolver ningún valor.
Solamente en el caso de que el método incluya los bloques try/catch/finally se
ejecutará el bloque catch que la captura o el bloque finally (si existe).

Todo método en el que se puede producir uno o más tipos de excepciones (y que no
utiliza directamente los bloques try/catch/finally para tratarlos) debe declararlas en el
encabezamiento de la función por medio de la palabra throws. Si un método puede
lanzar varias excepciones, se ponen detrás de throws separadas por comas, como por
ejemplo:

public void leerFichero(String fich) throws EOFException, FileNotFoundException {…}

Se puede poner únicamente una superclase de excepciones para indicar que se


pueden lanzar excepciones de cualquiera de sus clases derivadas. El caso anterior
sería equivalente a:

public void leerFichero(String fich) throws IOException {…}

Las excepciones pueden ser lanzadas directamente por leerFichero() o por alguno de
los métodos llamados por leerFichero(), ya que las clases EOFException y
FileNotFoundException derivan de IOException.

Se recuerda que no hace falta avisar de que se pueden lanzar objetos de la clases
Error o RuntimeException (excepciones implícitas).

CAPTURAR UNA EXCEPTION

Como ya se ha visto, ciertos métodos de los packages de Java y algunos métodos


creados por cualquier programador producen (“lanzan”) excepciones. Si el usuario
llama a estos métodos sin tenerlo en cuenta se produce un error de compilación con un
mensaje del tipo: “… Exception java.io.IOException must be caugth or it must be
declared in the throws clause of this method”. El programa no compilará mientras el
usuario no haga una de estas dos cosas:

1. Gestionar la excepción con una construcción del tipo try {…} catch {…}.
2. Re-lanzar la excepción hacia un método anterior en el stack, declarando que su
método también lanza dicha excepción, utilizando para ello la construcción throws en el
header del método.

El compilador obliga a capturar las llamadas excepciones explícitas, pero no protesta


si se captura y luego no se hace nada con ella. En general, es conveniente por lo
menos imprimir un mensaje indicando qué tipo de excepción se ha producido.
Bloques try y catch

En el caso de las excepciones que no pertenecen a las RuntimeException y que por lo


tanto Java obliga a tenerlas en cuenta habrá que utilizar los bloques try, catch y
finally.

El código dentro del bloque try está “vigilado”: Si se produce una situación anormal y se
lanza por lo tanto una excepción el control salta o sale del bloque try y pasa al bloque
catch, que se hace cargo de la situación y decide lo que hay que hacer. Se pueden
incluir tantos bloques catch como sean necesarios, cada uno de los cuales tratará un
tipo de excepción.

Las excepciones se pueden capturar individualmente o en grupo, por medio de una


superclase de la que deriven todas ellas.

El bloque finally es opcional. Si se incluye sus sentencias se ejecutan siempre, sea


cual sea la excepción que se produzca o si no se produce ninguna. El bloque finally se
ejecuta aunque en el bloque try haya un return.

En el siguiente ejemplo se presenta un método que debe "controlar" una IOException


relacionada con la lectura ficheros y una MyException propia:

void metodo1(){
...
try {
// Código que puede lanzar las excepciones IOException y MyException
} catch (IOException e1) {// Se ocupa de IOException simplemente dando aviso
System.out.println(e1.getMessage());
} catch (MyException e2) {
// Se ocupa de MyException dando un aviso y finalizando la función
System.out.println(e2.getMessage()); return;
} finally { // Sentencias que se ejecutarán en cualquier caso
...
}
...
} // Fin del metodo1

Relanzar una Exception

Existen algunos casos en los cuales el código de un método puede generar una
Exception y no se desea incluir en dicho método la gestión del error. Java permite que
este método pase o relance (throws) la Exception al método desde el que ha sido
llamado, sin incluir en el método los bucles try/catch correspondientes. Esto se
consigue mediante la adición de throws más el nombre de la Exception concreta
después de la lista de argumentos del método. A su vez el método superior deberá
incluir los bloques try/catch o volver a pasar la Exception. De esta forma se puede ir
pasando la Exception de un método a otro hasta llegar al último método del programa,
el método main().

El ejemplo anterior (metodo1) realizaba la gestión de las excepciones dentro del propio
método.

Ahora se presenta un nuevo ejemplo (metodo2) que relanza las excepciones al


siguiente método:

void metodo2() throws IOException, MyException {


...
// Código que puede lanzar las excepciones IOException y MyException
...
} // Fin del metodo2

Según lo anterior, si un método llama a otros métodos que pueden lanzar excepciones
(por ejemplo de un package de Java), tiene 2 posibilidades:

1. Capturar las posibles excepciones y gestionarlas.


2. Desentenderse de las excepciones y remitirlas hacia otro método anterior en el
stack para éste se encargue de gestionarlas.

Si no hace ninguna de las dos cosas anteriores el compilador da un error, salvo que se
trate de una RuntimeException.

Método finally {...}


El bloque finally {...} debe ir detrás de todos los bloques catch considerados. Si se
incluye (ya que es opcional) sus sentencias se ejecutan siempre, sea cual sea el tipo de
excepción que se produzca, o incluso si no se produce ninguna. El bloque finally se
ejecuta incluso si dentro de los bloques try/catch hay una sentencia continue, break o
return. La forma general de una sección donde se controlan las excepciones es por lo
tanto:

try {
// Código “vigilado” que puede lanzar una excepción de tipo A, B o C
} catch (A a1) {
// Se ocupa de la excepción A
} catch (B b1) {
// Se ocupa de la excepción B
} catch (C c1) {
// Se ocupa de la excepción C
} finally {
// Sentencias que se ejecutarán en cualquier caso
}

El bloque finally es necesario en los casos en que se necesite recuperar o devolver a


su situación original algunos elementos. No se trata de liberar la memoria reservada
con new ya que de ello se ocupará automáticamente el garbage collector.
Como ejemplo se podría pensar en un bloque try dentro del cual se abre un fichero
para lectura y escritura de datos y se desea cerrar el fichero abierto. El fichero abierto
se debe cerrar tanto si produce una excepción como si no se produce, ya que dejar un
fichero abierto puede provocar problemas posteriores. Para conseguir esto se deberá
incluir las sentencias correspondientes a cerrar el fichero dentro del bloque finally.

CREAR NUEVAS EXCEPCIONES


El programador puede crear sus propias excepciones sólo con heredar de la clase
Exception o de una de sus clases derivadas. Lo lógico es heredar de la clase de la
jerarquía de Java que mejor se adapte al tipo de excepción. Las clases Exception
suelen tener dos constructores:

1. Un constructor sin argumentos.


2. Un constructor que recibe un String como argumento. En este String se suele
definir un mensaje que explica el tipo de excepción generada. Conviene que este
constructor llame al constructor de la clase de la que deriva super(String).

Al ser clases como cualquier otra se podrían incluir variables y métodos nuevos. Por
ejemplo:

class MiExcepcion extends Exception {


public MiExcepcion() { // Constructor por defecto
super();
}
public MiExcepción(String s) { // Constructor con mensaje
super(s);
}
}

HERENCIA DE CLASES Y TRATAMIENTO DE EXCEPCIONES


Si un método redefine otro método de una super-clase que utiliza throws, el método de
la clase derivada no tiene obligatoriamente que poder lanzar todas las mismas
excepciones de la clase base. Es posible en el método de la subclase lanzar las
mismas excepciones o menos, pero no se pueden lanzar más excepciones. No
puede tampoco lanzar nuevas excepciones ni excepciones de una clase más general.

Se trata de una restricción muy útil ya que como consecuencia de ello el código que
funciona con la clase base podrá trabajar automáticamente con referencias de clases
derivadas, incluyendo el tratamiento de excepciones, concepto fundamental en la
Programación Orientada a Objetos (polimorfismo).

Apoyo bibliográfico:
Steven Holzner, Java2. Anaya Multimedia
Javier García de Jalón, José Ignacio Rodríguez, Iñigo Mingo · Aitor Imaz, Alfonso
Brazález · Alberto Larzabal · Jesús Calleja · Jon García Aprenda Java como si estuviera
en primero, Escuela Superior de Ingenieros Industriales

También podría gustarte