Uso de paquetes en Java
sábado, septiembre 1, 2001 at 2:00AM Paquetes en Java
Fecha de creación: 3.9.2001
Revisión 1.1 (27.10.2001)
Emili Miedes de Elías
emiedes@iti.upv.es
|
Introducción
En Java, es posible agrupar varias clases en una estructura llamada paquete. Un paquete no es más que un conjunto de clases, generalmente relacionadas entre sí de alguna manera. Es habitual diseñar una aplicación distribuyendo su funcionalidad entre varios paquetes, cuyas clases se comunican entre sí a través de interfaces bien definidas.
El uso de paquetes aporta varias ventajas frente a la programación sin paquetes. En primer lugar, permite encapsular funcionalidad en unidades con un cierto grado de independencia, ocultando los detalles de implementación. De esta forma se pueden conseguir diseños (e implementaciones) más limpios y elegantes.
Por otra parte, se potencia la reutilización de las clases desarrolladas. Es posible definir interfaces de uso de cada paquete, para que otros paquetes o aplicaciones puedan utilizar la funcionalidad implementada.
Además, el uso de paquetes permite la reutilización de los nombres de las clases, ya que el espacio de nombres de un paquete es independiente del de otros paquetes. El lenguage Java impone la restricción de que una clase debe tener un nombre único, dentro del paquete al cual pertenece. Sin embargo, es posible que dos clases tengan el mismo nombre, siempre y cuando pertenezcan a paquetes distintos.
Uso de paquetes
Para incluir una clase dentro de un paquete, únicamente hay que utilizar una sentencia package al principio del fichero fuente.
Por ejemplo:
package prueba;
public class Prueba
{
...
}
o con subpaquetes:
package prueba.prueba2;
public class Prueba
{
...
}
Nombre de paquetes y clases
El nombre completo de la clase (fully qualified name) está compuesto por el nombre del paquete al cual pertenece la clase además del nombre de la propia clase.
Los nombres completos de las clases del ejemplo anterior son prueba.Prueba y prueba.prueba2.Prueba.
Dado que prueba y prueba.prueba2 son paquetes distintos (aunque prueba.prueba2 sea un subpaquete de prueba), no hay colisión de nombres entre prueba.Prueba y prueba.prueba2.Prueba. Sin embargo, aunque el compilador permita usar el mismo nombre de esta forma, no es una práctica aconsejable porque el código tiende a ser confuso y propenso a errores.
En cuanto al nombre de los paquetes, Sun propuso en su momento un convenio para facilitar el uso de paquetes de terceros. Este convenio no es en absoluto obligatorio, aunque sí es aconsejable seguir alguno, o bien éste o bien otro, para mantener mínimamente organizadas nuestras clases. Según el convenio propuesto por Sun, el nombre de los paquetes desarrollados por una compañía se forma a partir del nombre del dominio DNS que esa compañía tiene registrado, invirtiendo el orden de sus miembros.
Por ejemplo, un paquete de gestión de stocks llamado manager desarrollado por IBM podría llamarse com.ibm.stocks.manager.
Uso de otros paquetes
Para usar clases de otros paquetes, no hay más que utilizar sentencias import, antes de la declaración de la clase.
Por ejemplo:
import java.lang.*;
import java.util.Vector;
import java.rmi.server.*;
Con el primer import le estamos indicando al compilador que vamos a importar todas las clases del subpaquete java.lang. (Este paquete contiene clases esenciales en la mayoría de aplicaciones Java, por lo que el compilador lo importa automáticamente, aunque no incluyamos una línea como la de arriba).
Con el segundo import, indicamos que sólo queremos importar la clase Vector del subpaquete java.util.
Con el tercer import, importamos todas las clases del paquete java.rmi.server.
Es posible utilizar una clase sin que esté incluída en un import, siempre y cuando utilicemos su nombre completo.
Por ejemplo:
java.util.Vector vector = new java.util.Vector(100, 10);
La ventaja de utilizar una sentencia import es que la anterior línea se puede reducir a
Vector vector = new Vector(100, 10);
Estructura jerárquica de directorios
Los ficheros .class pertenecientes a paquetes y subpaquetes deben estar organizados de forma adecuada para que tanto el compilador como la máquina virtual puedan utilizarlos.
Para ello, cada paquete se ubica en un directorio. Cada subpaquete se ubica en un directorio de nivel inferior, y así sucesivamente. Además, el nombre de cada directorio debe ser el del propio paquete.
Por ejemplo, las clases del paquete prueba deben estar situadas en un directorio llamado prueba. Dentro de éste, debe haber un subdirectorio llamado prueba2, en el que se sitúan las clases del paquete prueba.prueba2.
Así, cada (sub)paquete se corresponde con un (sub)directorio, y viceversa.
No existen restricciones en cuanto a dónde debe estar situado el primer nivel, pero una vez situado en algún directorio, los niveles descendientes deben respetar la jerarquía.
En el ejemplo anterior, podemos situar el directorio prueba en el directorio raíz de nuestro árbol de directorios (por ejemplo C:\), en un directorio de primer nivel (por ejemplo, C:\java), en uno de segundo, etc.
En algunos tutoriales, libros y manuales, a éste 'primer nivel' donde están situadas los directorios se le llama codebase.
Si nuestro codebase es C:\java\codebase, debe haber un directorio C:\java\codebase\prueba y otro C:\java\codebase\prueba\prueba2.
Ejecución de clases
A la hora de ejecutar una aplicación Java, hay que tener en cuenta algunas cosas. En primer lugar, hay que indicar el nombre completo de la clase a ejecutar.
Por ejemplo, si tenemos una clase Manager que pertenece al paquete com.ibm.manager, la orden para ejecutarla sería
java com.ibm.manager.Manager
Para que el anterior comando funcione tal cual, es necesario que el directorio actual desde el que se lanza la orden sea el codebase (por ejemplo, C:\java\codebase, si la clase Manager está en C:\java\codebase\com\ibm\manager\Manager.class).
Si estamos en otro directorio, es posible evitar el tener que cambiar de directorio, indicando a la máquina virtual qué directorio debe tomar como codebase, con una orden como
java -classpath C:\java\codebase com.ibm.manager.Manager
Puede ser que en nuestro árbol de directorios, tengamos todas las clases juntas a partir de un único directorio codebase, o que las tengamos separadas en varios. Puede ser que tengamos unas clases a partir de C:\java\codebase y otras a partir de D:\clases, por ejemplo.
Para facilitar la ejecución de las clases y evitar el tener que incluir parámetros demasiado largos en las invocaciones a la máquina virtual, es posible definir una variable de entorno llamada CLASSPATH que contenga todos los directorios codebase de nuestro sistema.
Utilizando esta variable, es posible invocar y utilizar clases que estén en cualquier parte, sin tener que pasarle un parámetro -classpath a la máquina virtual.
Por ejemplo, con CLASSPATH=C:\java\codebase;D:\clases podremos utilizar clases que estén situadas en esos dos directorios.
En el ejemplo anterior ya no es necesario el parámetro -classpath, por lo que la orden
java com.ibm.manager.Manager
pueda ser ejecutada desde cualquier directorio.
(No es posible suprimir
com, com.ibm o com.ibm.manager, puesto que forman parte del nombre completo de la clase).
Conclusión
El uso de paquetes en Java nos proporciona ventajas en cuanto a encapsulación, reusabilidad, independencia de espacios de nombres, etc. Únicamente se exige respetar la estructura jerárquica de los directorios, tanto para almacenar los ficheros.classcomo a la hora de hacer las invocaciones a las aplicaciones.
Recursos
Acerca del autor
Emili Miedes de Elías
Emili trabaja en el Instituto Tecnológico de Informática (Universidad Politécnica de Valencia) desarrollando en Java. En sus ratos libres, colabora con javaHispano y desarrolla software opensource (buscar por emiedes en SourceForge).
j2se 
Reader Comments