Antologia JAVA II
Antologia JAVA II
A. Introduccin
Los paquetes son el mecanismo por el que Java permite agrupar clases, interfaces,
excepciones y constantes. De esta forma, se agrupan conjuntos de estructuras de datos y de
clases con algn tipo de relacin en comn.
Con la idea de mantener la reutilizacin y facilidad de uso de los paquetes desarrollados es
conveniente que las clases e interfaces contenidas en los mismos tengan cierta relacin
funcional. De esta manera los desarrolladores ya tendrn una idea de lo que estn buscando
y fcilmente sabrn qu pueden encontrar dentro de un paquete.
B. Creacin de un paquete
a.) Declaracin
Para declarar un paquete se utiliza la sentencia package seguida del nombre del paquete que
estemos creando:
package NombrePaquete;
La estructura que ha de seguir un fichero fuente en Java es:
Para que los nombres de paquete puedan ser fcilmente reutilizados en toda una compaa o
incluso en todo el mundo es conveniente darles nombres nicos. Esto puede ser una tarea
realmente tediosa dentro de una gran empresa, y absolutamente imposible dentro de la
comunidad de Internet.
Por eso se propone asignar como paquetes y subpaquetes el nombre de dominio dentro de
Internet. Se ver un ejemplo para un dominio que se llamase japon.magic.com, un nombre
apropiado sera com.magic.japon.paquete.
c.) Subpaquetes
Cada paquete puede tener a su vez paquetes con contenidos parecidos, de forma que un
programador probablemente estar interesado en organizar sus paquetes de forma
jerrquica. Para eso se definen los subpaquetes.
Para crear un subpaquete bastar con almacenar el paquete hijo en un directorio
Paquete/Subpaquete.
As una clase dentro de un subpaquete como Paquete.Subpaquete.clase estar codificada en
el fichero Paquete/Subpaquete.java.
El JDK define una variable de entorno denominada CLASSPATH que gestiona las rutas en
las que el JDK busca los subpaquetes. El directorio actual suele estar siempre incluido en la
variable de entorno CLASSPATH.
C. Uso de un paquete
Con el fin de importar paquetes ya desarrollados se utiliza la sentencia import seguida del
nombre de paquete o paquetes a importar.
Se pueden importar todos los elementos de un paquete o slo algunos.
Para importar todas las clases e interfaces de un paquete se utiliza el metacaracter *:
import PaquetePrueba.*;
Tambin existe la posibilidad de que se deseen importar slo algunas de las clases de un
cierto paquete o subpaquete:
import Paquete.Subpaquete1.Subpaquete2.Clase1;
Para acceder a los elementos de un paquete, no es necesario importar explcitamente el
paquete en que aparecen, sino que basta con referenciar el elemento tras una especificacin
completa de la ruta de paquetes y subpaquetes en que se encuentra.
Paquete.Subpaquetes1.Subpaquete2.Clase_o_Interfaz.elemento
En la API de Java se incluyen un conjunto de paquetes ya desarrollados que se pueden
incluir en cualquier aplicacin (o applet) Java que se desarrolle.
D. mbito de los elementos de un paquete
Al introducir el concepto de paquete, surge la duda de cmo proteger los elementos de una
clase, qu visibilidad presentan respecto al resto de elementos del paquete, respecto a los de
otros paquetes.
Situacin del
elemento
private
sin
modificador
protected
public
En la misma clase
No
No
No
No
No
No
En una clase
en el mismo paquete
Por ejemplo una misma interfaz podra ser implementada en una versin de prueba de
manera poco ptima, y ser acelerada convenientemente en la versin definitiva tras conocer
ms a fondo el problema.
B. Declaracin
Para declarar una interfaz se utiliza la sentencia interface, de la misma manera que se usa la
sentencia class:
interface MiInterfaz {
int CONSTANTE = 100;
int metodoAbstracto( int parametro );
}
Se observa en la declaracin que las variables adoptan la declaracin en maysculas, pues
en realidad actuarn como constantes final. En ningn caso estas variables actuarn como
variables de instancia.
Por su parte, los mtodos tras su declaracin presentan un punto y coma, en lugar de su
cuerpo entre llaves. Son mtodos abstractos, por tanto, mtodos sin implementacin
C. Implementacin de una interfaz
Como ya se ha visto, las interfaces carecen de funcionalidad por no estar implementados
sus mtodos, por lo que se necesita algn mecanismo para dar cuerpo a sus mtodos.
La palabra reservada implements utilizada en la declaracin de una clase indica que la clase
implementa la interfaz, es decir, que asume las constantes de la interfaz, y codifica sus
mtodos:
class ImplementaInterfaz implements MiInterfaz{
int multiplicando=CONSTANTE;
int metodoAbstracto( int parametro ){
return ( parametro * multiplicando );
} }
En este ejemplo se observa que han de codificarse todos los mtodos que determina la
interfaz (metodoAbstracto()), y la validez de las constantes (CONSTANTE) que define la
interfaz durante toda la declaracin de la clase.
Una interfaz no puede implementar otra interfaz, aunque s extenderla (extends)
amplindola.
D. Herencia mltiple
Java es un lenguaje que incorpora herencia simple de implementacin pero que puede
aportar herencia mltiple de interfaz. Esto posibilita la herencia mltiple en el diseo de los
programas Java.
Si coinciden en su declaracin: se elimina uno de los dos, con lo que slo queda
uno.
Error: Excepciones que indican problemas muy graves, que suelen ser no
recuperables y no deben casi nunca ser capturadas.
Todas las excepciones tienen como clase base la clase Throwable, que est incluida en el
paquete java.lang, y sus mtodos son:
C. Funcionamiento
a.) Introduccin
Cuando el programador va a ejecutar un trozo de cdigo que pueda provocar una excepcin
(por ejemplo, una lectura en un fichero), debe incluir este fragmento de cdigo dentro de un
bloque try:
Pero lo importante es cmo controlar qu hacer con la posible excepcin que se cree. Para
ello se utilizan las clausulas catch, en las que se especifica que accin realizar:
try {
// Cdigo posiblemente problemtico
} catch( tipo_de_excepcion e) {
// Cdigo para solucionar la excepcin e
} catch( tipo_de_excepcion_mas_general e) {
// Cdigo para solucionar la excepcin e
}
En el ejemplo se observa que se pueden anidar sentencias catch, pero conviene hacerlo
indicando en ltimo lugar las excepciones ms generales (es decir, que se encuentren ms
arriba en el rbol de herencia de excepciones), porque el intrprete Java ejecutar aquel
bloque de cdigo catch cuyo parmetro sea del tipo de una excepcin lanzada.
Si por ejemplo se intentase capturar primero una excepcin Throwable, nunca llegaramos a
gestionar una excepcin Runtime, puesto que cualquier clase hija de Runtime es tambin
hija de Throwable, por herencia.
Si no se ha lanzado ninguna excepcin el cdigo contina sin ejecutar ninguna sentencia
catch.
Pero, y si quiero realizar una accin comn a todas las opciones?. Para insertar fragmentos
de cdigo que se ejecuten tras la gestin de las excepciones. Este cdigo se ejecutar tanto
si se ha tratado una excepcin (catch) como sino. Este tipo de cdigo se inserta en una
sentencia finally, que ser ejecutada tras el bloque try o catch:
try {
} catch( Exception e ) {
} finally {
// Se ejecutara tras try o catch
}
c.) Lanzamiento de excepciones: throw - throws
Ahora que ya sabemos cmo funciona este sistema, conviene ver al menos un pequeo
ejemplo, que ilustre al lector en el uso de las excepciones:
// Creo una excepcin personalizada
class MiExcepcion extends Exception {
MiExcepcion(){
super(); // constructor por defecto de Exception
}
MiExcepcion( String cadena ){
super( cadena ); // constructor param. de Exception
}
}
// Esta clase lanzar la excepcin
class Lanzadora {
void lanzaSiNegativo( int param ) throws MiExcepcion {
if ( param < 0 )
throw new MiExcepcion( "Numero negativo" );
}
}
class Excepciones {
public static void main( String[] args ) {
// Para leer un fichero
Lanzadora lanza = new Lanzadora();
FileInputStream entrada = null;
int leo;
try {
entrada = new FileInputStream( "fich.txt" );
while ( ( leo = entrada.read() ) != -1 )
lanza.lanzaSiNegativo( leo );
entrada.close();
System.out.println( "Todo fue bien" );
} catch ( MiExcepcion e ){ // Personalizada
System.out.println( "Excepcion: " + e.getMessage() );
} catch ( IOException e ){ // Estndar
System.out.println( "Excepcion: " + e.getMessage() );
} finally {
if ( entrada != null )
try {
Fichero cerrado
En el caso de que se produjese un error de E/S, al leer el primer nmero, sera:
Excepcion: java.io.IOException
Fichero cerrado
e.) Conclusiones
Por ejemplo, el siguiente programa utiliza dos hilos, el hilo general main, y el hilo thDemo
que creamos:
import java.io.*;
import java.net.*;
class ThreadDemo implements Runnable {
ThreadDemo() {
Thread thDemo = new Thread( this, "ThDemo" );
thDemo.start();
}
public void run() {
try {
Thread.sleep(3000);
} catch( InterruptedException e ) { }
System.out.println("Saliendo del hilo hijo");
}
public static void main( String args[] ){
new ThreadDemo();
try {
for ( int i = 5 ; i >0 ; i-- ) {
System.out.println(" Seg: " + i );
Thread.sleep(1000);
}
} catch( InterruptedException e ) { }
System.out.println("Saliendo del main");
}
}
Ambos hilos esperan utilizando el mtodo sleep() de la clase Thread; thDemo tres
segundos, y main cinco segundos. Java utilizar los tres segundos de thDemo para ir
esperando los tres primeros segundos del hilo main.
Por lo tanto la salida por pantalla al ejecutar el programa es:
prompt> java ThreadDemo
Seg: 5
Seg: 4
Seg: 3
Saliendo del hilo hijo
Seg: 2
Seg: 1
Saliendo del hilo main
MANEJO DE ARCHIVOS
import java.io.*;//no olviden importar esta librera al inicio de su
programa
public void escribir(String nombreArchivo){
File f;
f = new File("nombreArchivo");
//Escritura
try{
FileWriter w = new FileWriter(f);
BufferedWriter bw = new BufferedWriter(w);
PrintWriter wr = new PrintWriter(bw);
wr.write("Esta es una linea de codigo");//escribimos en el archivo
wr.append(" - y aqui continua"); //concatenamos en el archivo sin
borrar lo existente
//ahora cerramos los flujos de canales de datos, al cerrarlos el
archivo quedar guardado con informacin escrita de no hacerlo no se
escribir nada en el archivo
wr.close();
bw.close();
}catch(IOException e){};
}
EJEMPLO:
import java.io.*;
public String leer(String nombre){
//El parametro nombre indica el nombre del archivo por
ejemplo "prueba.txt"
try{
File f;
FileReader lectorArchivo;
//Creamos el objeto del archivo que vamos a leer
f = new File(nombre);
//Creamos el objeto FileReader que abrira el flujo(Stream) de
datos para realizar la lectura
lectorArchivo = new FileReader(f);
//Creamos un lector en buffer para recopilar datos a travs
del flujo "lectorArchivo" que hemos creado
BufferedReader br = new BufferedReader(lectorArchivo);
String l="";
//Esta variable "l" la utilizamos para guardar mas adelante
toda la lectura del archivo
String aux="";/*variable auxiliar*/
while(true){
//este ciclo while se usa para repetir el proceso de lectura,
ya que se lee solo 1 linea de texto a la vez
aux=br.readLine();
//leemos una linea de texto y la guardamos en la variable
auxiliar
if(aux!=null)
l=l+aux+"\n";
/*si la variable aux tiene datos se va acumulando en la