|
Tots els llenguatges de programació moderns, com Java,
són modulars. Tots organitzen la major part d'habilitats del llenguatge
en subconjunts de codi -llibreries, paquets, mòduls ...- que el
programador pot decidir incorporar als seus projectes. D'aquesta forma
s'optimitza el treball de disseny de programari. Pensa en els avantatges:
els projectes incorporen només allò que necessiten, és
molt senzill intercanviar codi entre programadors o empreses, el llenguatge
es fa molt fàcil d'ampliar només afegint llibreries, etc.
Cada llenguatge, però, planifica la modularitat de manera diferent.
En aquesta pràctica revisaràs la sintaxi de l'utilització
de paquets en Java, aprendràs a crear-ne
de propis i els tancaràs en llibreries. Finalment, estudiaràs
com s'ha de procedir per indicar al
que incorpori llibreries als seus projectes.
|
|
|
Paquets i llibreries |
|
|
|
|
|
Observaràs que hem utilitzat dues expressions: paquets i llibreries.
Expliquem què són abans de continuar.
- Un paquet és un lloc on desar classes. Si
tenim un grup de classes relacionades amb el mateix tipus de tasca,
és bo que estuguin totes en un paquet. Així doncs, un
paquet és un contenidor, una caixa o una carpeta de classes i
d'altres paquets. Podem fer paquets que continguin a l'interior classes
per a la gestió de fitxers, o classes que serveixen per a modificar
cadenes, o classes que serveixen per a tractar amb dates, etc. El nucli
de Java està organitzat així;
per exemple.
java.util
és un paquet dins d'un altre paquet: el paquet util
està dins el paquet java. És
un paquet que conté un grup de classes amb utilitats generals
del llenguatge.
java.math
també és un paquet dins d'un altre paquet. Com pots suposar,
es tracta d'eines per al tractament matemàtic.
Seguin aquest criteri, què creus que contenen aquests paquets?:
- java.text
- java.io
- java.security
- java.applet
Pràcticament tot el nucli del llenguatge està dins el
paquet java. Quan facis el disseny dels
treus propis paquets evitaràs batejar-los amb el nom de java,
crearies confusions.
- Una llibreria, en canvi, és un fitxer que
porta l'extensió jar i que conté
a l'interior, comprimit, un paquet o un grup de paquets. Si vas a la
carpeta /lib de la teva distribució
de Java veuràs que hi ha diferents
fitxers amb extensió jar: es tracta
de llibreries que utilitza el kit de Java
i que no formen part del nucli del llenguatge.
Les llibreries són la fòrmula convencional de distribuir
classes de Java: un cop tens escrites, ordenades
en paquets i revisades les teves classes, les tanques en una llibreria
i, movent només un fitxer, podràs incorporar tot el material
a projectes futurs o cedir el codi a qui t'interessi. Per a utilitzar-lo,
només farà falta indicar-li al compil·lador que
ha d'incorporar la llibreria al projecte.
Potser et preguntaràs com és que has estat fent sentències
d'importació (p. ex. import java.util.*)
en els darrers programes i, en canvi, no has hagut d'incorporar cap
llibreria al projecte. Pensa que totes les importacions les has fet
de classes incloses en el paquet java.*. La llibreria que conté
aquest paquet no cal carregar-la, el compil·lador la incorpora
per defecte. Una cosa similar passa amb les classes que estan incloses
en el paquet java.lang. Oi que has creat
objectes de la classe String sense cap sentència
d'importació? No ens cal perquè String
està en el paquet java.lang. Els
dissenyadors de Java han pensat que les
classes que estan a java.lang són
tan centrals i usuals que ens estalvien l'esforç de cridar
explícitament a l'importador.
Resumint una mica, Java estructura la modularitat i intercanvi de classes
de la forma següent:
Producció de Codi reusable
|
|
Utilització de Codi reusable
|
Escriure
les classes distribuint-les en paquets amb sentències package.
|
 |
Tancar
els paquets en una llibreria creant un fitxer .jar |
|
Incorporar
la llibreria, el fitxer .jar, al projecte
|
 |
Utilitzar
els paquets de la llibreria amb sentències import
|
PAQUETS
|
|
LLIBRERIES
|
|
LLIBRERIES
|
|
PAQUETS
|
Repassem, en primer lloc, la sintaxi i lògica d'importació
de paquets i després posarem en pràctica la producció
de paquets i llibreries i la reutilització de codi.
|
|
|
Sentències d'Importació
|
|
|
|
|
|
En aquests darrers mòduls has estat utilitzant sentències
d'importació de l'estil
import java.util.ArrayList; o
bé
import java.util.*;
Saps que serveixen perquè el compil·lador localitzi una
classe o un grup de classes en el paquet on estan desades i, d'aquesta
forma, poder-les utilitzar en els nostres programes. Si crees un objecte
ArrayList i et descuides de posar la sentència
d'importació a la part superior de la classe que estàs escrivint,
el compil·lador no sabrà en quina carpeta localitzar aquesta
classe i et donarà un error en temps de compil·lació.
Primer haurà buscat ArrayList dins de
java.lang. Com que l'esmentada classe no està
en aquest paquet, l'haurà buscat en el directori arrel del nostre
projecte; com que aquí tampoc no hi és, intentarà
buscar un paquet java.util entre les llibreries
instal·lades; finalment, farà saltar l'error.
|
|
|
|
|
|
Amb asterisc o sense |
|
|
|
|
|
|
Pots importar classes concretes o pots importar paquets sencers. És
idèntic fer una importació així:
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
que fer aquesta:
import java.util.*;
Amb la primera, el compil·lador sap trobar només les tres
classes citades mentre que amb la segona pot trobar qualsevol classe del
paquet util (no pot trobar, però, les
classes que hi puguin haber en els paquets que estan dins del paquet util).
Tot i que sembla més senzill, es desaconsella la utilització
de l'asterisc en les sentències d'importació. Perquè?
per un problema de legibilitat. Forma part dels protocols de bons costums
de programació Java. Està demostrat
que és més fàcil de llegir (a ulls humans, al compil·lador
li és indiferent) una classe que explicita les importacions que
una classe que fa importacions genèriques amb asterisc.
|
|
|
|
|
|
Presentació correcta |
|
|
|
|
|
|
Ja has vist que les sentències d'importació s'han d'escriure
fora i damunt de la classe. S'han d'escriure en l'espai
que hi ha entre la declaració de paquet package
i el capçal de la classe. Per exemple:
package asolans;
import java.util.Iterator;
public class Inventari() {
...
No hi ha normes estrictes sobre com s'han d'ordenar
les sentències d'importació, tot i que, a efectes de legibilitat,
es recomana:
- Posar les sentències d'importació per ordre alfabètic.
- Deixar una línia en blanc en importacions procedents de diferents
paquets.
Per exemple, aquesta seria una bona ordenació:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
Possiblement ara penses que tot això és una pèrdua
de temps: evitar asteriscs, ordenar sentències o separar-les fan
créixer el temps de desenvolupament i no t'aporten avantatges directes.
Es tracta, però, d'elements que donen qualitat al codi que fas.
Si algun dia et contracten per a programar en Java,
el teu cap segurament esperarà de tu que produeixis codi homologat
i de qualitat. De la mateixa forma que t'agradarà rebre'l a tu
si et toca modificar o ampliar un programa existent.
No tot són males notícies: els IDEs professionals tenen
en consideració aquests problemes i fan la vida més fàcil
al programador: són capaços de fer importacions intel·ligents
per a evitar els asteriscs i saben formatar i ordenar les entrades import.
|
|
|
|
|
|
Creació de paquets |
|
|
Imagina que treballes en una empresa de programari. Estàs integrat
en un equip de programadors Java que desenvolupa
un projecte per a una important multinacional. El grup té la feina
distribuïda i a tu t'ha tocat la tasca d'anar preparant utilitats
de gestió de fitxers i de cadenes per a la resta de l'equip -oblida't
de començar a treballar fent feines massa creatives!-.
L'empresa és diu "Egon Soft" i el projecte que
desenvolupeu Ciclop. Tot el programari Java
que desenvolupa la teva empresa s'integra en un paquet, amb el
nom egonsoft. Tots i cadascun dels projectes
de l'empresa tenen el seu paquet. Com que treballem en el projecte Ciclop,
tots els integrants de l'equip anirem escrivint classes que posarem dins
el paquet egonsoft.ciclop. A tu t'ha tocat fer
utilitats, el teu paquet de sortida és, com deus estar imaginant,
egonsoft.ciclop.util.
De totes les utilitats del projecte, tu t'encarregues de gestionar dos
apartats: utilitats de cadena i utilitats de fitxer. Les primeres les
posarem a egonsoft.ciclop.util.string i les
segones a egonsoft.ciclop.util.file.
|
|
|
|
|
 |
Obre el BlueJ i crea un nou projecte
que es digui utils. Obre l'opció de menú
Edita | Nou paquet. Aquesta acció t'obre una caixa
on pots donar el nom del paquet que vols crear. Escriu el següent:
|
|
|
|
|
|
Clica a Accepta i el
et crearà un grup de carpetes, les unes dins de les altres: una
carpeta que es diu egonsoft, a dins d'egonsoft una carpeta
que es diu ciclop i així successivament fins arribar a la
carpeta file.
Els paquets, doncs, s'organitzen en carpetes. I aquestes carpetes no
són només virtuals: són reals, físiques, les
trobaràs a dins de la carpeta del projecte.
Obre la carpeta del projecte utils. Al seu
interior trobaràs les carpetes que t'he indicat. A mesura que vagis
escrivint les classes a cada paquet, els fitxers *.java
i els fitxers compil·lats *.class també
els trobaràs dins la carpeta corresponent. Aquesta forma de funcionament
fa bastant senzilla l'ordenació de classes en Java.
Per a "navegar" amb el
pels paquets, només et cal fer un doble-clic sobre la icona en
forma de carpeta amb el nom del paquet que vols revisar.
|
|
|
 |
|
|
Ara crea el segon paquet: egonsoft.ciclop.util.string
seguint el mateix procediment: Editar | Nou Paquet
i el nom complet del paquet.
Crearem una classe d'utilitats per a cadena que contingui un mètode
per a resoldre el que ens han encarregat: necessitem poder fer substitucions
de paraules dins d'una cadena. Donada una cadena n'hem de retornar una
altra on totes les incidències d'un patró han de ser substituïdes
per un altre patró. Per exemple, en la frase "El
vol 5267 amb destinació a París ha estat cancel·lat"
hem de poder substituir la cadena París
per la cadena Londres i que retorni "El
vol 5267 amb destinació a Londres ha estat cancel·lat".
Navega fins a l'interior del paquet string.
Crea una nova classe que es digui StringUtil.
Obre l'editor i observa com l'expert del
ha escrit aquesta primera línia:
|
|
|
|
|
|
package
egonsoft.ciclop.util.string; |
|
|
És la marca de paquet. Qualsevol classe que forma part d' un paquet
ha de tenir com a primera línia el nom qualificat -sencer- del
paquet. No oblidis que no n'hi ha prou amb posar el fitxer amb el codi
font de la classe a la carpeta del paquet, la primera línia sempre
ha de contenir el nom del paquet.
Substitueix el contingut de la classe que acabes de crear per aquest:
|
|
|
|
|
|
package
egonsoft.ciclop.util.string;
/**
* @author Angel Solans
* @version 11-may-2004
*
*/
public class StringUtil {
/**
* Evitem la instanciació
*/
private StringUtil() {
}
/**
* Substitueix a "cadena" el Substring
"cerca"
* per "substitueix"
* @param cadena, cadena a revisar
* @param cerca, subcadena que busquem
* @param substitueix, subcadena que substitueix
al patró
* @return la cadena modificada
*/
public static String replace(String cadena, String
cerca,
String substitueix) {
int s = 0;
int e = 0;
StringBuffer result =
new StringBuffer();
while ((e = cadena.indexOf(cerca,
s)) >= 0) {
result.append(cadena.substring(s,
e));
result.append(substitueix);
s
= e+cerca.length();
}
result.append(cadena.substring(s));
return result.toString();
}
}
|
|
|
|
|
|
Observa alguna de les peculiaritats de la classe que hem creat:
- Hem creat un únic constructor i l'hem fet privat: aquesta classe
no es podrà instanciar. Prova de crear un objecte de la classe.
no et dóna la possibilitat de fer-ho. No ho pots fer amb el botó
dret sobre la icona de la classe i, dins del codi tampoc podràs
fer això:
StringUtil stringutil = new StringUtil();
- Com que no puc instanciar objectes de la classe, tots els mètodes
han de ser de tipus static.
Complicar així les coses quin avantatge té?
- Com a mínim, et facilitarà la utilització de
la classe quan després la necessitis, perquè no n'hauràs
de crear instàncies. En lloc de fer:
StringUtil stringutil = new StringUtil();
String novacadena =
stringutil.replace
("El vol 5267 a París
ha estat cancel·lat", "París","Londres");
Podràs fer
String novacadena=
StringUtil.replace
("El
vol 5267 a París ha estat cancel·lat", "París","Londres");
El codi és més senzill, legible i igualment eficaç.
Observa la rutina de substitució. S'ha utilitzat la classe StringBuffer
en lloc d'una String perquè és
una classe més eficient a l'hora d'afegir fragments de cadena.
Et veus capaç de modificar el mètode tot substituïnt
l'StringBuffer per una String?
Verifica el funcionament del mètode. Recorda que des del
has de cridar-lo directament sobre la icona de la classe perquè
no en pots instanciar objectes.
|
|
|
|
|
|
Crear llibreries |
|
|
|
|
|
Tot i que no hem fet massa feina, només amb aquesta classe ja
estàs en condicions d'experimentar la creació de llibreries.
El
facilita molt aquesta feina. Amb el projete utils
obert tria l'opcio de menú Projecte | Exportar.
T'obrirà una caixa com aquesta:
|
|
|
|
|
|
|
|
|
|
|
|
Deixa l'opció incloure font (si
no marques aquesta opció la llibreria només contindrà
els fitxers compil·lats .class). Clica sobre el botó
Continua. El
et demanarà en quina carpeta vols deixar la llibreria.
- Pots crear-te una carpeta específica per a les teves llibreries
- Pots desar-la en qualsevol lloc de l'ordinador que t'interessi
- o pots deixar-la en una carpeta que el
té destinada per a les llibreries d'usuari, que es carreguen
automàticament cada vegada que obres l'entorn.
Triarem aquesta darrera opció.
Deixa la llibreria a c:/Archivos de Programa/BlueJ/lib/userlib
(si tens el
instal·lat a Archivos de programa).
També pots triar posar a la llibreria el nom de fitxer que vulguis.
Acceptarem el que ens suggereix el nostre entorn de treball: utils.
Clica sobre el botó Crear.
Busca amb l'explorador del Windows la carpeta on has deixat la llibreria.
Trobaràs un petit fitxer d'uns 2k que es diu utils.jar.
Ja tens la llibreria a punt per a utilitzar-la on faci falta.
Tanca el
i torna'l a obrir: la llibreria utils.jar ja està disponible.
Comprova-ho anant a Eines | Preferències
i triant la pestanya "Llibreries". Ha de tenir
l'aspecte següent:
|
|
|
|
|
|
|
|
|
Utilitzar llibreries |
|
|
|
|
|
Si has deixat la llibreria a userlib ja la pots utilitzar. Si l'has
deixat en un altra carpeta l'hauràs d'afegir des de l'opció
Eines | Preferències | Llibreries amb el procediment Afegir.
Crea un nou projecte i posa-li de nom ciclop.
Utilitzarem el formatador de cadenes que has preparat.
Crea una classe ControlVols amb el següent
contingut:
|
|
|
|
|
|
import
egonsoft.ciclop.util.string.StringUtil;
/**
*
* @author Angel Solans
* @version 11-05-2004
*/
public class ControlVols {
/**
* Mètode constructor per a objectes
* de la classe ControlVols
*/
public ControlVols() {
}
/**
* Substitueix una destinació per
una altra
* @param cadena, cadena a substituir
* @param desti1, desti inicial
* @param desti2, desti substitut
*/
public String substitueixDestinacio(String cadena,
String desti1, String desti2)
{
return StringUtil.replace(cadena,desti1,desti2);
}
}
|
|
|
|
|
|
Ara podem accedir i utilitzar les classes de la nostra llibreria.
Compila la classe que acabes de crear i veuràs
que tot funciona. Això posa de manifest que ja podem accedir i
utilitzar les classes de la nostra llibreria, que s'ha inclòs amb
la sentència import.
A mesura que vagis treballant amb Java (cosa que succeirà en els mòduls que s'aniran publicant)
veuràs la utilitat i la importància del treball amb llibreries
per fer efectiva la funció multiplataforma del llenguatge Java. |
|
|
|
 |