LF Java Handbook
Rel. 1.0
11.12.2006
Luigi Ferrari
Indice
1. GENERALITA'........................................................................................................ 1
1.1. Tipi di programmi in Java.................................................................................................1
1.2. Applicazioni Enterprise.................................................................................................... 1
1.2.1. Servlet....................................................................................................................... 1
1.2.2. JavaBean.................................................................................................................. 1
2. INSTALLAZIONE.................................................................................................... 2
2.1. Windows.......................................................................................................................... 2
2.1.1. Run da DOS.............................................................................................................. 2
2.1.2. Windows 2000 e seguenti......................................................................................... 2
2.2. Linux................................................................................................................................ 2
2.2.1. Configurazione JDK.................................................................................................. 2
2.3. Configurazione server Apache (vedi lfwebserver.txt)...................................................... 3
2.3.1. Accesso al server...................................................................................................... 3
2.4. Organizzazione delle directory.........................................................................................4
2.5. Dove mettere le librerie jar...............................................................................................4
3. USO.........................................................................................................................5
3.1. Operazioni base...............................................................................................................5
3.1.1. Compilazione.............................................................................................................5
3.1.2. Run............................................................................................................................6
3.1.3. Visualizzazione di applet con AppletViewer.............................................................. 6
3.1.4. Visualizzazione di applet da browser........................................................................ 7
3.1.5. Creazione librerie .jar................................................................................................ 7
3.1.6. Creazione librerie .jar eseguibili................................................................................ 7
3.2. JBuilder............................................................................................................................ 7
3.2.1. Costruzione di applicazioni........................................................................................7
3.2.2. Editor......................................................................................................................... 7
3.2.3. Package.................................................................................................................... 8
3.2.4. Uso di librerie............................................................................................................ 8
3.2.5. Inserimento di immagini come sfondo di bottoni o altro............................................ 8
3.3. Bluej................................................................................................................................. 8
3.3.1. Installazione DOS......................................................................................................8
3.3.2. Installazione LINUX...................................................................................................9
3.3.3. Difetti......................................................................................................................... 9
3.3.4. Modo standard di lavorare.........................................................................................9
3.3.5. Uso di librerie (jar)..................................................................................................... 9
3.4. NetBeans......................................................................................................................... 9
3.4.1. Setting dell'editor....................................................................................................... 9
3.5. Eclipse........................................................................................................................... 10
3.6. Progettazione con UML................................................................................................. 10
3.7. Standard SIMS...............................................................................................................10
4. PROGRAMMAZIONE........................................................................................... 11
4.1. Definizioni...................................................................................................................... 11
4.1.1. Classe..................................................................................................................... 11
4.1.2. Attributo................................................................................................................... 11
4.1.3. Metodo.................................................................................................................... 11
4.1.4. Costruttore...............................................................................................................11
4.1.5. Istanza di un oggetto della classe........................................................................... 11
4.1.6. Interfaccia................................................................................................................11
4.2. Regole di scrittura.......................................................................................................... 11
4.2.1. Regole per la scelta dei nomi.................................................................................. 11
4.2.2. Documentazione del codice: utility javadoc.............................................................12
4.3. Tipi di dato..................................................................................................................... 12
4.3.1. Check su variabile booleana restituita come oggetto..............................................12
4.4. Variabili (attributi)........................................................................................................... 12
4.4.1. Modificatori di accesso............................................................................................ 12
4.4.2. Inzializzazione delle variabili................................................................................... 13
4.4.3. Definizione di nuovi tipi di costanti, costanti condivise tra piu' classi...................... 13
4.5. Costruttori...................................................................................................................... 13
4.5.1. Come creare un costruttore che ne richiama un altro............................................. 14
4.5.2. Costruttori private e protected................................................................................. 14
4.6. Metodi............................................................................................................................ 14
4.6.1. Tipi di metodi........................................................................................................... 14
4.6.2. Effetti collaterali....................................................................................................... 14
4.6.3. Modificatori di accesso............................................................................................ 14
4.6.4. Passaggio di parametri............................................................................................15
4.7. Il metodo main............................................................................................................... 15
4.8. this................................................................................................................................. 16
4.9. Stringhe..........................................................................................................................16
4.9.1. Creazione di una stringa......................................................................................... 16
4.9.2. Metodi......................................................................................................................16
4.9.3. Confronto di stringhe............................................................................................... 17
4.9.4. Copia di stringhe..................................................................................................... 17
4.9.5. Buffer per la costruzione di stringhe........................................................................17
4.9.6. Conversione di stringhe da e verso tipi primitivi...................................................... 17
4.9.7. StringTokenizer....................................................................................................... 18
4.10. Array............................................................................................................................ 18
4.10.1. length e arraycopy.................................................................................................18
4.10.2. Array di oggetti...................................................................................................... 19
4.10.3. Passaggio di array ad un metodo..........................................................................19
4.10.4. Array dinamici........................................................................................................19
4.10.5. Oggetti protected...................................................................................................19
4.11. Package....................................................................................................................... 19
5. INTERAZIONE TRA GLI OGGETTI......................................................................20
5.1. Classi interne................................................................................................................. 20
5.2. Ereditarieta'.................................................................................................................... 20
5.2.1. Classi astratte..........................................................................................................20
5.2.2. Oggetti protected.....................................................................................................20
5.2.3. La classe Object......................................................................................................20
5.3. Interfacce....................................................................................................................... 20
5.3.1. Uso delle interfacce: definizione di comportamenti................................................. 20
5.3.2. Uso delle interfacce: definizione di costanti comuni tra le classi.............................21
5.3.3. Esempio d'uso: casello di un ponte......................................................................... 21
5.3.4. Ereditarieta' multipla con Java.................................................................................22
5.4. Composizione................................................................................................................ 23
6. COLLEZIONI DI OGGETTI................................................................................... 24
6.1. Criteri di scelta............................................................................................................... 24
6.2. Iteratori...........................................................................................................................24
6.3. Modalita' di utilizzo......................................................................................................... 24
6.3.1. Uso degli array........................................................................................................ 24
6.3.2. Uso delle ArrayList.................................................................................................. 24
6.3.3. Uso dei Vector.........................................................................................................25
6.3.4. Uso delle mappe..................................................................................................... 26
6.3.5. Uso dei Set (HashSet).............................................................................................26
7. FLUSSI.................................................................................................................. 28
7.1. Scopo.............................................................................................................................28
7.1.1. Flussi di dati, lettori e scrittori.................................................................................. 28
7.2. File di testo: Reader e Writer......................................................................................... 28
7.2.1. Lettura di caratteri da file.........................................................................................28
7.2.2. Schema generale per la lettura............................................................................... 28
7.2.3. Schema generale per la scrittura............................................................................ 29
7.2.4. Metodi di controllo................................................................................................... 29
7.3. File binari: flussi............................................................................................................. 29
7.3.1. Lettura di bytes........................................................................................................29
7.4. Esempio di gestione di flussi di dati: ConsoleReader.................................................... 29
7.4.1. Classe File...............................................................................................................30
7.4.2. Classe FilenameFilter..............................................................................................31
7.4.3. Come creare una directory......................................................................................31
7.5. Flussi di oggetti - serializzazione................................................................................... 31
7.5.1. Serializzazione di oggetti che non implementano Serializable................................32
7.5.2. Serializzazione di oggetti tramite JavaBean............................................................32
7.6. Accesso casuale............................................................................................................ 32
7.6.1. Classe RandomAccessFile..................................................................................... 32
7.7. Flussi su rete di telecomunicazioni................................................................................ 32
7.7.1. Esecuzione di script su server con passaggio di un solo parametro.......................32
7.7.2. Esecuzione di script su server con passaggio di parametri: uncgi..........................33
8. APPLET................................................................................................................ 35
8.1. Caratteristiche................................................................................................................35
8.2. Protezione......................................................................................................................35
8.3. Struttura del file HTML per la chiamata di applet...........................................................35
8.4. Scrittura del codice........................................................................................................ 36
8.5. Passaggio di parametri ad una applet........................................................................... 36
8.6. Classe che fa da applet e da applicazione grafica.........................................................36
8.7. Tips sulle applet............................................................................................................. 37
8.7.1. Memorizzazione di dati su stream (condivisione di dati tra applet)......................... 37
8.7.2. Installazione di applet su Web Server (TO DO)...................................................... 37
8.7.3. Installazione su login diversa da quella del Web Server (TO DO).......................... 37
8.7.4. Come visualizzare un file sul server (TO DO)......................................................... 37
8.7.5. Come lanciare comandi sul server (TO DO)........................................................... 37
8.7.6. Visualizzazione del nome dell'host..........................................................................37
8.7.7. Come aprire una nuova finestra.............................................................................. 37
8.7.8. Come ridisegnare una nuova finestra pop-up su se stessa (TO DO)..................... 38
8.7.9. Come esportare dati da una applet (TO DO).......................................................... 38
8.7.10. Debug e Log di una applet.................................................................................... 38
8.7.11. Messaggi sulla barra di stato.................................................................................38
9. GRAFICA.............................................................................................................. 39
9.1. Gestione degli eventi..................................................................................................... 39
9.1.1. Esempio completo...................................................................................................40
9.2. Classi interne................................................................................................................. 41
9.3. Come combattere lo sfarfallio delle animazioni............................................................. 41
10. SWING................................................................................................................ 42
10.1. Classi........................................................................................................................... 42
10.1.1. JOptionPane..........................................................................................................42
10.1.2. JFrame.................................................................................................................. 42
10.1.3. Menu': JMenuBar, JMenu, JMenuItem, JPopupMenu...........................................43
10.1.4. JButton.................................................................................................................. 43
10.1.5. JFileChooser......................................................................................................... 45
10.1.6. JTable....................................................................................................................45
10.1.7. Layout....................................................................................................................45
10.1.8. JList....................................................................................................................... 45
11. THREAD..............................................................................................................46
11.1. Eventi di un thread....................................................................................................... 46
11.2. Definizione del metodo run()........................................................................................46
11.2.1. Estensione della classe Thread............................................................................ 46
11.2.2. Implementazione dell'interfaccia Runnable........................................................... 47
12. GESTIONE DEGLI ERRORI (EXCEPTION)....................................................... 49
12.1. Eccezioni controllate.................................................................................................... 49
12.2. Eccezioni non controllate............................................................................................. 49
12.3. Gestione delle eccezioni.............................................................................................. 49
12.3.1. Sollevare una eccezione in caso di malfunzionamento.........................................49
12.3.2. Intercettazione delle eccezioni.............................................................................. 50
12.3.3. Creazione di un nuovo tipo di eccezione...............................................................51
12.3.4. Esempi di uso delle eccezioni: FifoQueue............................................................ 51
13. DESIGN PATTERNS.......................................................................................... 54
13.1. Singleton...................................................................................................................... 54
13.1.1. Esempio di implementazione (versione mia, non e' quello classico).....................54
13.2. SenderArgument..........................................................................................................56
13.3. Iteratore........................................................................................................................56
13.4. Observer...................................................................................................................... 57
13.4.1. Realizzazione tramite Observer-Observable.........................................................57
13.4.2. Realizzazione tramite JavaBean........................................................................... 57
13.4.3. Applicazione di Observer: pattern MVC (Model View Controller)..........................58
13.4.4. Java Message Service (JMS)................................................................................59
13.4.5. Problemi del pattern Observer.............................................................................. 59
13.5. Command.................................................................................................................... 59
13.5.1. Insieme di comandi che producono output diversi (es. gitelf)............................... 59
13.5.2. Comando che deve essere lanciato da piu' fonti: Action.......................................60
13.6. Proxy............................................................................................................................62
13.7. Facade......................................................................................................................... 62
14. Esempi di Object Oriented Design...................................................................63
14.1. Forza 4.........................................................................................................................63
15. APPLICAZIONI ENTERPRISE........................................................................... 64
15.1. Servlet..........................................................................................................................64
15.1.1. Esempio di servlet................................................................................................. 64
15.2. JavaBean..................................................................................................................... 64
15.2.1. Creazione di un file jar con il javabean..................................................................64
15.2.2. Loading di un javabean in un IDE......................................................................... 64
16. JDBC - JAVA E I DATABASE............................................................................65
16.1. Connessione e disconnesione dal database............................................................... 65
16.2. Select........................................................................................................................... 65
16.3. Chiamata di stored procedure......................................................................................66
16.4. Insert e delete.............................................................................................................. 66
16.5. Istruzioni DDL.............................................................................................................. 66
17. DATABASE SERVER HSQLDB.........................................................................67
17.1. Installazione................................................................................................................. 67
17.2. Utility............................................................................................................................ 67
17.2.1. DatabaseManager.................................................................................................67
17.2.2. ScriptTool.............................................................................................................. 67
17.3. Versione server............................................................................................................67
17.4. Organizzazione delle dir.............................................................................................. 67
17.4.1. Esempio di script per la creazione di un database................................................68
17.4.2. Esempio di avvio del server.................................................................................. 68
17.4.3. Esempio di avvio del manager del database in versione standalone e server......68
17.4.4. Esempio per vedere il contenuto del database..................................................... 69
18. TIPS: Soluzione di problemi............................................................................. 70
18.1. Standard main - DA RISOLVERE................................................................................70
18.2. log - DA FARE............................................................................................................. 70
18.3. Out Of Memory............................................................................................................ 70
18.4. Attributi che devono contenere valuta..........................................................................70
18.5. Variabili che cambiano valore tra una chiamata e l'altra..............................................70
18.6. Check su variabile booleana restituita come oggetto.................................................. 70
18.7. NullPointerException....................................................................................................70
18.8. Stampa con Java - DA RISOLVERE........................................................................... 70
18.9. Pulizia della memoria (garbace collection forzata)...................................................... 71
18.10. Calcolo del tempo di elaborazione.............................................................................71
18.11. Controllo delle versione della JRE in esecuzione...................................................... 71
18.12. Appleviewer non visualizza applet per problemi con X..............................................71
18.13. Netscape su Linux: visualizzazione di applet.............................................................71
18.14. Errori di arrotondamento............................................................................................ 71
18.15. Conversione decimale-binario................................................................................... 71
18.16. Permissions sulle applet............................................................................................ 72
18.17. Random - Generazione di comportamenti casuali.....................................................72
18.18. Date and Time - Visualizzazione data corrente......................................................... 72
18.19. Date and Time - Classi standard............................................................................... 72
18.20. Problemi con piu' finestre...........................................................................................73
18.21. Configurazione di una applicazione........................................................................... 73
18.22. Associazione di un programma java al tipo di un file sotto Windows.........................73
18.23. Creazione di un link per un programma java............................................................. 74
18.24. Organizzazione di una applicazione in librerie...........................................................74
19. ALGORITMI........................................................................................................ 75
19.1. Strutture dati astratte................................................................................................... 75
19.2. Algoritmi matematici.....................................................................................................77
19.2.1. Potenza n-esima di numero reale (metodo degli invarianti di ciclo)...................... 77
19.2.2. Calcolo della radice quadrata................................................................................77
19.2.3. Calcolo di pi greco con l'ago di Buffon.................................................................. 77
20. ARGOMENTI AVANZATI DI JAVA.................................................................... 79
20.1. Riflessione................................................................................................................... 79
20.2. Riflessione e classi Proxy............................................................................................ 79
20.2.1. Uso di classi proxy per il trace...............................................................................79
21. FONDAMENTI DELLA PROGRAMMAZIONE AD OGGETTI............................ 80
21.1. Oggetti e classi............................................................................................................ 80
21.1.1. Argomenti.............................................................................................................. 80
21.2. Approfondimenti sulla definizione di classi.................................................................. 80
21.3. Interazione tra oggetti.................................................................................................. 80
21.4. Raggruppamenti (collezioni) di oggetti.........................................................................80
21.5. Librerie e documentazione...........................................................................................81
21.6. Test e debug................................................................................................................ 81
21.7. Disegno di classi.......................................................................................................... 81
21.8. Ereditarieta' e polimorfismo..........................................................................................81
21.9. Tecniche avanzate di astrazione: interfacce e classi astratte......................................81
21.10. Gestione degli errori...................................................................................................81
21.11. Disegno di applicazioni.............................................................................................. 81
21.12. Esercizi sui cicli..........................................................................................................81
22. DOCUMENTAZIONE.......................................................................................... 83
22.1. Cay Horstmann, Big java............................................................................................. 83
22.2. Cay Horstmann, Concetti di informatica e fondamenti di java 2.................................. 83
23. API LF................................................................................................................. 84
23.1. lfapi package................................................................................................................84
23.1.1. ConfigFile.............................................................................................................. 84
23.1.2. ConnectionManager.............................................................................................. 84
23.1.3. cpfile...................................................................................................................... 84
23.1.4. EnvironmentMap................................................................................................... 84
23.1.5. FileInputHashMap................................................................................................. 84
23.1.6. FileUtility................................................................................................................84
23.1.7. Log........................................................................................................................ 84
23.1.8. StringUtility............................................................................................................ 84
23.1.9. ThumbnailBuilder.................................................................................................. 85
23.1.10. ThumbnailSetBuilder........................................................................................... 85
23.1.11. txtfile.................................................................................................................... 85
23.1.12. URLReader......................................................................................................... 85
23.2. lfapi.GUI package........................................................................................................ 85
23.2.1. ErrorWindow..........................................................................................................85
23.2.2. GenericTablePanel................................................................................................85
23.2.3. FormLayout........................................................................................................... 85
23.2.4. StatusBar...............................................................................................................85
24. ESEMPI DI CODICE........................................................................................... 86
24.1. JTable con diverse funzionalita'................................................................................... 86
24.2. Form layout.................................................................................................................. 98
LF Java Handbook
LF Java Handbook
1. GENERALITA'
1.1. Tipi di programmi in Java
Esistono tre tipi di programmi java
• applicazioni da console:
• applicazioni grafiche: programmi con interfaccia utente gestibile non solo da tastiera, ma
anche con il mouse e tramite pulsanti, menu' a discesa, campi per l'inserimento testo,
finestre... che forniscono l'intefaccia utente; es: Word, Excel, Bluej..
• applet: che programmi integrati in pagine web e inviate insieme ad esse per aumentare le
capacita' dell'HTML (animazioni, interfacce grafiche...).
Non possono modificare in alcun modo il contenuto del computer su cui sono eseguite per
motivi di sicurezza.
1.2. Applicazioni Enterprise
Sono sviluppate per girare su server: sono le servlet.
1.2.1. Servlet
Sono eseguite sul server remoto.
In pratica una servlet e' una API utilizzata dal Web Server per fornire nuovi servizi. Di solito
non hanno alcuna interfaccia grafica.
Vengono attivate una volta solo alla attivazione del Server, possono ricordare lo stato. Inoltre
possono comunicare tra loro anche attraverso pipeline.
1.2.2. JavaBean
work in progress..
-1Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
2. INSTALLAZIONE
2.1. Windows
www.javasoft.com -> jdk.
Mettere in autoexec.bat il path aggiornato con la
c:\programmi\jdk1.2.2\bin) e dichiarare la variabile di ambiente
directory
bin
del
jdk
(i.e.
CLASSPATH con Set:
Set CLASSPATH=.
Old: Set CLASSPATH=c:\Programmi\jdk1.2.2\lib\classes.zip
WINDOWS
1.2.2
da CDROM dev 71 "100% PROGRAMMAZIONE" si installa versione 1.2.2
directory:
c:\programmi\jdk122 (era proposto \jdk1.2.2)
poi edit \autoexec.bat per aggiungere al PATH c:\programmi\jdk122\bin
1.4.0_01 (su Dell Windows Xp)
Directory c:\programmi\java\j2sdk1.4.0_01
Modificata a mano la variabile di ambiente PATH
Start/pannello di controllo/prestazioni e manutenzione/Sistema/avanzate/
variabili d'ambiente/path
Aggiunto: c:\programmi\java\j2sdk1.4.0_01\bin
2.1.1. Run da DOS
Per il run direttamente da DOS nel caso dica che la classe e' NotFound occorre settare
classpath in modo da comprendere la directory che contiene il .class.
Se non fosse gia' settata puo' bastare
set classpath=.
2.1.2. Windows 2000 e seguenti
Modifica delle variabili di ambiente con
RisorseComputertastodx/Proprieta'/avanzate/Variabili d'ambiente e
si modifica la singola variabile.
E' necessario essere amministratori.
2.2. Linux
2.2.1. Configurazione JDK
User root
Si prende J2SDK1.4.0i...BIN (CD Java) e lo si mette sotoo /lftmp
poi chmod a+x e lo si esegue.
Scompatta nella directory corrente sotto j2sdk1.4.0_01.
mkdir /usr/java
cp -r j2sdk1.4.0_01 /usr/java
login sapilf
vi .bash_profile: aggiunto
#
# Java SDK 1.4.0 (LF 12.3.2003)
#
JAVA_HOME=/usr/java/j2sdk1.4.0_01
rm -fr $HOME/.netscape/java
rm -fr $HOME/.netscape/plugins/javaplugin.so
-2Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
export NPX_PLUGIN_PATH=$JAVA_HOME/jre/plugin/i386
cd ~/java
mkdir lib
login root (copia del driver jdbc di oracle)
cd /p3/oracle/817/jdbc/lib
cp classes111.zip /home/sapilf/java/lib
login sapilf
cd java/sapicommon
bld -c
Compilazione delle api sapi: tutto bene a parte
deprecated
in SapiExceptionDialog.java.
login sapibin
mkdir
mkdir
mkdir
mkdir
mkdir
mkdir
Per SIMS il server e' sotto $SAPIBIN_HOME/httpd/html
in questa dir ci vanno a finire i .jar
(i.e. $SAPIBIN_HOME/httpd/html/login/sapicommon.jar)
httpd
httpd/html
(httpd ci arriva con link da /home/httpd)
httpd/cgi-bin
httpd/html/dataviewer
httpd/html/login
httpd/html/cashbook
login sapilf
cd java/dataviewer
bld -c
Compilazione e copia librerie...
login root (Abilitazione Java Console)
vi .bash_profile: aggiunto
#
# Java SDK 1.4.0 (LF 12.3.2003)
#
JAVA_HOME=/usr/java/j2sdk1.4.0_01
rm -fr $HOME/.netscape/java
rm -fr $HOME/.netscape/plugins/javaplugin.so
export NPX_PLUGIN_PATH=$JAVA_HOME/jre/plugin/i386
e settata /bin/bash come shell di default in /etc/passwd
Avvio di Netscape e apertura dell'URL
file:/usr/java/j2sdk1.4.0_01/jre/ControlPanel.html
dove e' possibile settare i parametri della Console Java.
Base:
- abilita Java plug-in
- Mostra console
- Mostra finestra di dialogo Eccezioni
Avanzate (lasciate le standard)
Altre.. lasciate cosi'.
2.3. Configurazione server Apache (vedi lfwebserver.txt)
Directory dove mettere i file accessibili del server:
/home/httpd/cgi-bin
/home/httpd/html
In realta', per le esigenze di SAPI html e' un link simbolico a $SAPIBIN_HOME:
cd /home/httpd
ln -s /vol03/sapibin/httpd/html html
2.3.1. Accesso al server
-3Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Linux: utilizzare Netscape.
Windows: utilizzare IExplorer.
Esempi di URL:
http://L3/
/home/httpd/html/index.htm
http://L3/oracle.htm
http://L3/testapplet/poligono.html
http://L3/cgi-bin/test.sh
visualizza (se esiste)
2.4. Organizzazione delle directory
c:\java (o altro equivalente)
bin
-> javac, java, appletviewer...
lib
-> classes.zip
2.5. Dove mettere le librerie jar
Ci sono almento tre possibilita':
• nella dir lib/ext della jre
• nella stessa dir dell'applicazione
• in una qualunque dir settando opportunamente CLASSPATH
Avevo trovato da qualche parte una bella spiegazione (Guida alla programmazione JSP ?).
-4Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
3. USO
3.1. Operazioni base
3.1.1. Compilazione
javac [-cp classdir_or_jar] [-d outdir] file1.java [filen.java...]
Opzioni:
• -cp (classpath) specifica da dove prendere le classi definite negli import. E' possibile
dichiarare una directory o un file .jar Se sono piu' di una e' possibile separare dir e file jar
con ";".
• -d (i.e. ../classes) dice dove creare i .class.
ATTENZIONE: sembra che almeno sotto Linux non basti indicare i .jar delle classi nel
$CLASSPATH ma sia necessario indicarlo nella linea di comando.
i.e.: non trova
package netscape.javascript.*
dopo lunghe ricerche ho scoperto che e' nella
/usr/lib/netscape/java/classes/java40.jar
ma occorre compilare con
javac -d ../classes -classpath /usr/lib/netscape/java/classes/java40.jar
Idem per i driver Oracle messi in $HOME/java/lib/classes111.zip
WINDOWS:
Sotto windows andare in una shell MS-DOS e spostarsi nella directory dove si vuole mettere
il file .java (sorgente). Con edit lo si scrive.
Conviene inoltre avere una finestra aperta su edit e una su javac e java.
NOTA: sotto DOS non sono ammessi i nomi lunghi per i file (max 8.3).
Dir fa vedere file del tipo nomefi~1.jav, ma a destra mostra il nome completo.
Per compilare e' necessario dare i comandi con i nomi veri dei file e l'estensione "java".
LINUX:
Esempio di script sotto Linux per la compilazione automatica
#! /bin/sh
PACKAGE=shipgate
set -a
OUTPUT_JAR=$SAPIBIN_HOME/httpd/html/$PACKAGE/$PACKAGE.jar
CLASSPATH=$CLASSPATH:\
$JAVA_HOME/jre/lib/javaplugin.jar:\
$HOME/java/lib/sapicommon.jar:$HOME/java/lib/classes111.zip:\
$HOME/java/lib/dx.jar:$HOME/java/lib/dbswing.jar
cp $HOME/java/lib/sapicommon.jar $SAPIBIN_HOME/httpd/html/$PACKAGE
cp $HOME/java/lib/classes111.zip $SAPIBIN_HOME/httpd/html/$PACKAGE
OPTION="none"
if [ $# -eq 1 ]
then
OPTION=$1
fi
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
-5-
LF Java Handbook
if [ $OPTION = "-c" ]
then
rm -f classes/$PACKAGE/*.class
# compliamo tutti i java inseme poiche' sono correlati
javas=
for name in src/$PACKAGE/*.java
do
javas=`echo " ${javas} ${name} "`
done
name=$javas
echo compiling $name ...
javac -d classes/$PACKAGE $name
REPLY=$?
if [ $REPLY != 0 ];
then
exit 1
fi
echo "all compiled... please wait..."
sleep 10
fi
cd classes/$PACKAGE
echo $OUTPUT_JAR
jar cvf $OUTPUT_JAR ./*.class img/*
exit 0
3.1.2. Run
Attenzione a maiuscole/minuscole
java [-cp directory_or_jar] NomeClasse
(.class)
Se il file (.class) e' in un .jar si deve mettere nell'opzione -cp
java -cp NomeFile.jar NomeClasse
Se ci fossero piu' dipendenze si devono separare nel cp con ;.
Per il run da DOS si deve settare il classpath in modo da comprendere la dir dove e' presente
il file .class:
set classpath=.
in molti casi e' sufficiente.
3.1.3. Visualizzazione di applet con AppletViewer
appletviewer URL
Attenzione che richiede il .html e non il .class Per lanciare una applet contenuta in un file.jar
occorre mettere ARCHIVE= nel tab che invoca la classe.
LINUX:
Se Appletviewer fallisce dicendo impossibile al server invalid DISPLAY
Errore: non puo' trovare server per localhost:0:0
si deve dare da root
xhost +
che abilita l'accesso al server da qualunque client.
DOS Ricordarsi che deve essere stata installata ls JVM (cioe' il JRE)
-6Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
3.1.4. Visualizzazione di applet da browser
Si ottiene aprendo il file .html.
Per visualizzare le applet e' necessario avere installato i plug-in (in pratica la JRE).
L'unico libro che ne parla e' Horstmann-Cornell Java2, pag.524 che dice che occorre
installare il plug-in...
LINUX:
Netscape 4.72 non riesce a caricare gli applet: dice che e' un problema di major number.
ATTENZIONE: verificare sempre i parametri di lancio delle applet (i.e. ORACLE_SID)
3.1.5. Creazione librerie .jar
DOS: bldjar.bat del progetto Gitelf
echo off
echo echo - Building lfgite.jar ...
echo rem copy ..\..\lfcommon\lib\lfapi.jar .
cd ..
@jar cvf bin\lfgite.jar *.class LogoLF100x100.jpg beansgite\*.class dbgite\*.class
rem del lfapi.jar
cd bin
echo echo - lfgite.jar builded.
echo REM @jar cvf dati.jar config data bin txt2xml*.txt
@jar cvf dati.jar config
echo echo - dati.jar builded.
echo if ERRORLEVEL
goto err
0 goto ok
:err
echo "bldjar: ...errore durante l'esecuzione"
goto done
:ok
echo "bldjar successfully executed."
:done
pause
LINUX: vedi prima.
3.1.6. Creazione librerie .jar eseguibili
Todo..
3.2. JBuilder
3.2.1. Costruzione di applicazioni
- new Application
3.2.2. Editor
• tab stop: e' definito a livello di Project properties, esiste la possibilita' di definire quelli di
default.
• CTL-SHIFT-<spazio> visualizza i parametri di un metodo
-7Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
3.2.3. Package
<nomeprogetto>/classes contiene le classi del package
Lancio di applicazioni in package
javaw Eurino/EurinoApp
3.2.4. Uso di librerie
Durante le fasi di sviluppo e' possibile definire delle librerie nelle properties del project
(path/Required library).
ATTENZIONE: l'ordine e' importante (e difatti e' possibile cambiarlo)
JBCL
dbSwing
oracle2 (classes111.zip)
Per utilizzarle durante la fase di running invece non ho ancora trovato come fare direttamente
dalla configurazione di run.
Conviene invece creare un file html di lancio (che JBuilder lancia con AppletViewer)
contenente le direttive ARCHIVE="li1, lib2..".
ATTENZIONE: e' necessario far ripartire JBuilder affinche' veda le librerie modificate.
3.2.5. Inserimento di immagini come sfondo di bottoni o altro
Non e' possibile direttamente (c'e' la drop list vuota).
Occorre prima definire la nuova immagine con
ImageIcon nome = new ImageIcon("nomefile.gif");
il file deve essere nella dir dove sta la classe.
Attivando designer c'e' in basso a sx il nuovo oggetto <nome> negli Other.
FORSE INUTILE:
Click sopra, nella finestra a destra si sceglie ImageObserver e li'
si indica il bottone o altro che la potra' utilizzare.
Andando poi con il designer sul bottone e nella proprieta' Icon dovrebbe essere possibile
selezionare l'immagine.
3.3. Bluej
E' un ambiente spartano ma molto orientato alla programmazione ad oggetti, scritto in java,
per Windows e Linux, free.
E' vantaggioso rispetto alla linea di comando da DOS ed ha vantaggi nell'approccio anche
rispetto a JBuilder.
3.3.1. Installazione DOS
dir di installazione/lib/bluej.defs consente di personalizzare parzialmente l'ambiente:
bluej.userHome=E\:\\DellUser\\Luigi\\Java
bluej.editor.tabsize=3
#LF bluej.compiler.type=internal
bluej.compiler.type=javac
bluej.compiler.executable=javac
Attenzione: per settare l'apertura della doc delle api di java non serve cambiare il valore in
bluej.defs ma e' necessario andare nelle opzioni di bluej: dalla form del programma scegliere
Strumenti
/
Preferenze
/
Varie
e
mettere
la
directory
corretta
(i.e.
-8Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
D:\DocJava\docs\api\index.html).
3.3.2. Installazione LINUX
1. scaricato Bluej-135.jar da www.bluej.org
2. da root
mkdir /usr/share/bluej
chmod 777 /usr/share/bluej
cp xxx/bluej-135.jar /usr/share/bluej
xhost +
per abilitare l'uso del server da parte di chiunque
3. da sapilf:
cd /usr/share/bluej
java -cp bluej-135.jar Installer
Directory: lasciare /usr/share/bluej
Trova da solo la JVM.
Crea un eseguibile Bluej
vi .bash_profile: aggiunto
PATH=$PATH:/usr/share/bluej
3.3.3. Difetti
• crea i .class nella stessa dir dei .java (provato modificando bluej.defs mettendo
blue.compiler.executable javac -d ../classes (con e senza doppi apici) ma non funziona).
• new project: richiede che i file non esistano gia' oppure siano in una dir diversa da quella
che si intende creare (e si puo' utilizzare add source from file..).
• fino a che e' in esecuzione lock sui file che ha utilizzato, anche su progetti chiusi.
• oltre che i .class crea anche del .ctxt nella directory corrente
• non ha molte delle facilitazioni dei moderni ambienti di sviluppo: completamento
automatico, elenco degli argoemnti dei metodi, collegamento con la documentazione...
3.3.4. Modo standard di lavorare
Scelgo dir padre di tutti i progetti (i.e. Luigi/Java/src)
New Project-> nome del progetto grosso (i.e. luigi; crea una dir con il
nome scelto e ci mette un bluej.pkg)
New Package crea sottodir con il suo bluej.pkg
Add source from file oppure import da altra dir (copia tutto, comodo)
Per prendere dei progetti gia' fatti utilizzare import.
3.3.5. Uso di librerie (jar)
Vanno incluse da menu' e occorre ripartire per ricaricarle.
Attenzione che, se si modificano, i test non funzionano perche'l'ambiente continua ad
utilizzare quelle caricate all'avvio. Per lo sviluppo mettere in ambiente separato e una volta
definitive creare .jar, poi far ripartire bluej.
3.4. NetBeans
working in progress..
Sembra molto promettente, e' facilmente espandibile, free..
3.4.1. Setting dell'editor
L'editor di default ha dei caratteri molto piccoli. Usare Tools/Options/Editor Settings e poi
Java Editor per mettere almeno 16 come dimensione dei caratteri; poi tab size 3.
Per la stampa e' necessario scurire i commenti altrimenti nella stampa con laser b/n non si
vede nulla. Nella stessa sezione Java Editor scegliere "Font and colors" e mettere 0, 51, 51 per
-9Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
i block comments e single line comments.
3.5. Eclipse
E' una alternativa a NetBeans, free..
3.6. Progettazione con UML
E' possibile utilizzare Violet (realizzato da Cay Horstmann, free), molto semplice.
Alcuni disegni di questo manuale sono realizzati con quello.
Una alternativa e' ArgoUML.
3.7. Standard SIMS
Si lavora sotto Windows, JBuilder 6 Professional; il collegamento con Oracle c'e' comunque
attraverso la rete. Attenzione: jdk deve essere 1.4.0. Per configurare Jbuilder6 con jdk 1.4
occorre mettere il jdk nella directory della versione 1.3.
Si copia poi tutto sotto Sun e si ricompila.
- 10 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
4. PROGRAMMAZIONE
4.1. Definizioni
4.1.1. Classe
Definisce lo stato ed i comportamenti di un insieme di oggetti omogenei.
Il suo stato e' definito dagli attributi, il suo comportamento dai metodi.
Puo' ereditare stato e comportamenti da un'altra classe (ereditarieta' singola).
Puo' implementare nessuna, uno o piu' interfacce (cioe' comportamenti richiesti per poter
definire la sua appartenenza ad una categoria, come quella degli oggetti salvabili in un file).
Puo' essere necessario anche definire un costruttore.
4.1.2. Attributo
Definisce una parte dello stato di un oggetto. Ne esistono di sue tipi.
• Variabili di istanza: cambiano fra le istanze
• Variabili di classe: uguali per tutti gli oggetti della stessa classe
4.1.3. Metodo
Definisce il comportamento della classe.
Puo' avere al massimo un valore di ritorno.
4.1.4. Costruttore
Serve per costruire un oggetto. Di solito contiene l'inizializzazione dello stato.
Il nome del costruttore coincide con quello della classe.
Possono essere definiti piu' costruttori, ognuno con parametri diversi in numero e/o tipo.
4.1.5. Istanza di un oggetto della classe
Consiste nella creazione di un oggetto della classe.
La parola chiave e' "new".
4.1.6. Interfaccia
Definisce, senza implementarli, una serie di comportamenti che una classe deve realizzare
per poter entrare a far parte di una categoria di classi (ad esempio quelle salvabili su file con
una sola istruzione).
Possono essere utilizzate anche per definire delle costanti comuni tra piu' classi.
4.2. Regole di scrittura
• di ogni classe definire prima di tutto la struttura dati, mettendola in testa e commentandola
adeguatamente.
• dividere chiaramente le funzioni interne (private) da quelle pubbliche (public)
• indicare chiaramente i costruttori
4.2.1. Regole per la scelta dei nomi
classi: iniziale maiuscola.
attributi e metodi: iniziale minuscola.
costanti: tutto maiuscolo.
package: tutto minuscolo, se possibile di una sola parola, al singolare.
- 11 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
4.2.2. Documentazione del codice: utility javadoc
@author @todo
4.3. Tipi di dato
int
-2e-9 - 2e9 (Integer.MIN_VALUE - Integer.MAX_VALUE)
long
-9e-18 - 9e18
double
10e300
short
16 bit
byte
8 bit, -127 - +128
float
23 cifre binarie, 7 decimali
boolean possibili solo i valori true e false.
char 2 byte in codifica Unicode
BigInteger, BigDecimal: precisione qualunque, sono memorizzati come stringhe
BigInteger a = new BigInteger("12345678901234567890123456789012");
ATTENZIONE: i dati primitivi (ad es. i numeri) in Java non sono oggetti, quindi non e'
possibile chiamare dei metodi su di loro.
NOTA Per le valute usare int, long o BigInteger con unita' di misura il piu' piccolo decimale.
Non usare double!!
Esistono poi dei tipi di dato che sono Oggetti che rappresentano numeri e altri dati primitivi
possono essere utilizzati ovunque sono utilzzati questi, in maniera ovviamente meno efficiente:
Integer
Integer
Float
Double
Boolean
i = new Integer(4);
i1 = new Integer("43");
f = new Float(4.0);
d = new Double(4.50);
b = new Boolean("true");
Conversione:
int i2 = i.intValue();
boolean b1 = b.booleanValue();
Conversione da stringa:
int i3 = Integer.parseInt("34");
boolean b2 = Boolean.parseBoolean("false");
// metodo statico
// metodo statico
Da JDK 5.0 la conversione e' invece automatica.
4.3.1. Check su variabile booleana restituita come oggetto
if (((Boolean)config.get("DEBUG")).booleanValue())
4.4. Variabili (attributi)
Ci sono variabili della classe, variabili di istanza e variabili locali:
• variabili di classe: si dichiarano con static e assumono lo stesso valore in tutte le istanze
della classe; se cambio il loro valore in una istanza lo cambio in tutte le altre;
• variabili di istanza: sono dichiarate all'interno della classe e sono diverse in ogni istanza
• variabili locali: sono dichiarate all'interno dei metodi e sono conosciute solo da loro.
Nota: non mettere variabili locali con lo stesso nome dei campi della classe!
4.4.1. Modificatori di accesso
• public: chiunque puo' modificare i dati. Da non usare se non in caso di effettiva necessita'.
• protected: sono visibili solo nel package (valore di default).
• private: si puo' accedere ai campi private solo con i metodi della classe
- 12 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
• static: definisce variabili di classe: ce ne e' una per tutte le istanze. Il valore iniziale deve
essere assegnato nella dichiarazione (all'atto del caricamento della classe) e non nel
costruttore (verrebbe altrimenti cambiata ad ogni nuova istanza della classe)
• final: definisce le costanti. Di solito si usa assieme a static per averne una in tutta la classe.
Difficilmente si dichiarano costanti non static (sarebbero costanti per il singolo oggetto e
non per l'intera classe).
Uso: NomeClasse.COSTANTE
Esempio: (classe Math):
Classe Math:
Classe Math:
Classe Console:
Math.PI (3.1415...)
Math.E
(2.7178...)
System.out
4.4.2. Inzializzazione delle variabili
• valore predefinito: al caricamento della classe;
• nel costruttore: alla creazione di un nuovo oggetto;
• lazy initialization, inizializzazione pigra: solo la prima volta che la variabile viene
utilizzata. Si usa un metodo con lo stesso nome (v. Metzker, Design pattern in Java).
Esempio di inizializzazione pigra
int attributo;
public int attributo(int x){
if (attributo == null) attributo = x;
return attributo;
}
4.4.3. Definizione di nuovi tipi di costanti, costanti condivise tra piu' classi
Per fare un controllo sui tipi conviene utilizzare una classe ed una interfaccia (Vedi Metzker Design Patterns - cap.2). Chi le usa deve implementare l'interfaccia (la classe non ha metodi
ma solo un costruttore protected vuoto).
Definizione:
public class Classificazione {
protected Classificazione() {}
}
public interface CostantiClassificazione {
static final Classificazione COSTANTE1 = new Classificazione();
static final Classificazione COSTANTE2 = new Classificazione();
}
Uso:
public class Esempio implements CostantiClassificazione {
Classificazione codice;
...
if (this.codice == COSTANTE1) ...
...
Con l'uso delle interfacce (che sono implementate dalla classe) e' possibile omettere il nome
della classe davanti alle costanti utilizzate.
4.5. Costruttori
- 13 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
4.5.1. Come creare un costruttore che ne richiama un altro
public class NomeClasse {
protected int i1;
protected NomeClasse next;
// e' una lista
// prima si mette quello piu' generale
public NomeClasse(int el, NomeClasse n) {
i1 = el ; next = n ;
}
public NomeClasse(int el) {
this(el, null);
}
public NomeClasse() {
next = null;
}
...
}
4.5.2. Costruttori private e protected
• private: utilizzati quando si usa ad esempio il pattern Singleton (con cui si instanzia
sempre un solo oggetto di una classe)
• protected: sempre nel Singleton, una mia soluzione permette solo al gestore del pool di
risorse di istanziarne di nuove: per far cio' la risorsa e il gestore sono in un package
apposito e il costruttore della risorsa e' protected.
4.6. Metodi
4.6.1. Tipi di metodi
• Metodi accessori: non modificano lo stato attuale (i.e getSaldo()) Inoltre non modificano il
valore dei parametri passati
• Metodi modificatori: sono quelli che modificano l'oggetto cui si riferiscono Come regola
dovrebbero restituire void.
• Metodi statici: non hanno parametri impliciti (cioe' l'oggetto su cui sono chiamati), ma solo
espliciti: i.e. Math.sqrt(x) Esistono classi (classi immodificabili) che hanno solo metodi
accessori e nessun metodo modificatore: ad esempio la classe String, che non modifica
mai il valore dell'oggetto creato: anche il metodo substring restituisce una copia della parte
di stringa che si vuole.
4.6.2. Effetti collaterali
Si hanno quando i metodi accessori provocano cambiamenti sullo stato o sull'uscita: vedi
getSaldo.
Graduatoria di comportamento dei metodi:
• ottimo: metodi accessori che non producono cambiamenti su eventuali i parametri espliciti.
Nessun effetto collaterale (i.e getSaldo)
• buono: metodi modificatori che non producono cambiamenti su eventuali parametri espliciti.
Nessun effetto collaterale (i.e. prelievo)
• sufficiente: metodi che cambiano un parametro esplicito (i.e. trasferisciSu)
• insufficiente: metodi che cambiano una variabile statica (cioe' di i classe: se lo chiamo due
volte da' risultati diversi) o che stampano messaggi su output (i.e. System.out)
4.6.3. Modificatori di accesso
• public: qualunque metodo di qualunque classe che abbia accesso ad una istanza della
- 14 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
classe lo puo' chiamare
• private: possono essere chiamati solo in metodi della stessa classe; da usare per metodi
che non interessano a chi usa la classe e per i metodi che non possono essere facilmente
modificati se cambia l'implementazione della classe.
• static: agiscono su una classe e non su una istanza per cui possono essere usati senza
creare prima l'istanza della classe.
Non hanno bisogno di un parametro implicito.
Esempio: Math.sqrt(x): il metodo sqrt della classe Math (non di un oggetto Math).
Ogni applicazione, ad eccezione delle applet, ha il metodo statico main:
infatti all'inzio della esecuzione di un programma non esiste ancora alcun oggetto per cui
main DEVE essere statico.
Si usano quando si vogliono incapsulare operazioni di tipi esclusivamente numerico (i
numeri NON sono oggetti). Di solito conviene metterli in classi separate, simile alla classe
Math standard.
NOTA: possono accedere solo a campi statici della classe.
Esempio: i metodi delle classi Console e Math:
double x = Math.pow(3,0,1);
Math.round(3.14);
ATTENZIONE: non e' possibile utilizzarli applicati ad un numero:
errato:
corretto:
int dolllars = (int)price.round();
int dolllars = (int)Math.round(price);
/* ERR */
/* OK */
ESEMPIO:
/**
* Aggiunge gli interessi ad un conto.
* Esempio di metodo statico (o di classe)
* La prima versione, commentata, non funziona perche' tenta di modificare
* un parametro esplicito NUMERICO
*/
// public static void aggiornaSaldo(double saldo, double tassoInteresse)
// {
//
double interessi= saldo * tassoInteresse/100;
//
saldo = saldo + interessi;
// }
public static void aggiornaSaldo(Conto conto, double tassoInteresse) {
double interessi= conto.getSaldo() * tassoInteresse/100;
conto.deposito(interessi);
}
4.6.4. Passaggio di parametri
Avviene per valore per i tipi di dato semplici, per riferimento per gli oggetti.
Non e' possibile quindi passare una variabile double e modificarla in un metodo.
Non e' possibile cambiare il riferimento ad un oggetto sostituendolo con un altro.
4.7. Il metodo main
public static void main (String args[]) throws IOException {
for (int i+0; i<args.length; i++)
System.out.println("Argomento "+i+" vale "+args[i]);
}
Note:
- 15 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
• arg[0] e' il primo argomento passato (non il nome del programma)
• non sono riuscito a trovare l'equivalente di return del C per uscire in caso di errore.
• e' definito static perche' deve essere lanciato prima che sia creato un oggetto della classe
(anzi, potrebbe non essere mai creato).
• il main puo' chiamare solo metodi statici.
• la lista di argomenti puo' essere ottenuto come ArrayList.
TIP: e' possibile convertire args in una lista anziche' usare l'array di Stringhe (da v. 1.4):
public static void main(String args[]) {
List argsList = Arrays.asList(args);
Iterator it = argsList.iterator();
while (it.hasNext()) {
System.out.println("Arg: "+it.next());
}
...
}
4.8. this
Consente di fare riferimento all'oggetto e non all'istanza particolare:
e' da usare ad esempio se si vuole lo stato corrente di un qualsiasi oggetto (parametro
implicito del metodo) all'interno di un metodo:
Esempio: se per l'oggetto a si chiama il metodo leggi con a.leggi(...) e nel metodo c'e'
l'istruzione
System.out.println(this)
si stampa lo stato corrente dell'oggetto a (infatti System.out.println chiama il metodo toString
della classe di a).
4.9. Stringhe
Le stringhe sono oggetti "immutabili" per cui non e' possibile, ad esempio, farne direttamente
una copia.
La stringa nulla ("") e' diversa da null.
Non e' possibile derivare delle classi da String (e' final (?)).
4.9.1. Creazione di una stringa
String s1 =
String s2 =
char dati[]
String s3 =
"abc";
new String("abc");
= {'a', 'b', 'c'};
new String(dati);
4.9.2. Metodi
Attenzione: quelli che restiruiscono String non modificano la stringa di partenza, ma
restituiscono una nuova stringa.
- + concatenazione
- String substring(start, primoEscluso)
String substring(start) prende fino alla fine
Esempio: s = "Hello world";
s.substring(0,4) => "Hell"
s.substring(7,12) => "world"
- String toLowerCase()
- String toUpperCase()
- boolean equals(String s) ritorna True se la stringa e' uguale a s passata.
- long length()
- 16 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
-
boolean equalsIgnoreCase(String s) confronto case insensitive
String trim()
rimuove spazi a inizio e fine stringa.
int indexOf(char)
-1 se non trovato.
char charAt(int i)
carattere nella i-esima posizione
4.9.3. Confronto di stringhe
String s1 = "Rob", s2 = "Rob", s3, s4 = "Roberto";
String s5 = new String("Rob"); // e' un oggetto sicuramente diverso
s3 = s1;
Valgono le seguenti regole:
- Java ottimizza le stringhe costanti crendo un solo oggetto se sono uguali
("Rob" e "Rob" nell'esempio);
- s1 == s2
true (vedi sopra)
s1 == s3
true
s1.equals(s3)
true
s1 == "Rob"
true (stesso oggetto "Rob")
s1 == s4.substring(0,3)
false
s1.equals(s4.substring(0,3))
true
s1 == s5
false
4.9.4. Copia di stringhe
Si puo' fare in diversi modi:
s2 = s1 + "";
s2 = s1.subString(0);
s2 = s1.clone();
4.9.5. Buffer per la costruzione di stringhe
Se si devono costruire delle stringhe a pezzi conviene utilizzare la classe StringBuffer che
ottimizza evitando di creare nuovi oggetti per ogni passaggio.
L'efficienza aumenta notevolmente.
StringBuffer buf = new StringBuffer();
for (int i=0; i < len; i++) {
for (int j=0; j< i; j++)
buf.append ("*");
buf.append("\n");
}
return buf.toString();
4.9.6. Conversione di stringhe da e verso tipi primitivi
Stringa -> tipo primitivo
String s1 = new String("320");
String s2 = new String("2.23");
// errato o obsoleto: int i = Integer.ValueOf(s1).intValue();
int i = new Integer(s1).intValue();
meglio ancora:
int i = Integer.parseInt(s1); // si usa il metodo statico della classe Integer
// errato o obsoleto : double d = Double.valueOf(s2).doubleValue();
double f = new Double(s2).doubleValue();
double d = Double.parseDouble(s2);
Tipo primitivo -> stringa
int a = 14;
int b = 23.33;
String s3 = Integer.toString(a);
String s4= Double.toString(b);
- 17 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Alternative:
s3 = String.valueOf(a);
s3 = "" + a;
// questa e' quella che uso io
4.9.7. StringTokenizer
Consente di prendere i token di una stringa.
Attenzione che i token vengono eliminati, se servono dovono essere ripristinati.
Esempio:
StringTokenizer tokenizedLine = new StringTokenizer(line, ",");
while (tokenizedLine.hasMoreElements()) {
String token =tokenizedLine.nextToken();
// fa qualcosa con token..
}
4.10. Array
Dichiarazione di un array
private double[] data;
// non inizializzato
Array inizializzato con tre elementi di tipo string
private String[] strarr= { "prima", "seconda", "terza" };
Nel costruttore o altrove si inizializza:
data = new double[10];
e si assegnano eventualmente i valori:
data[0]
data[1]
data[2]
data[3]
data[4]
=
=
=
=
=
1.0;
1.344;
9.99;
0.998;
1.872;
NOTA: gli array sono inizializzati con 0 se sono di int o double con false se sono di boolean,
con null se sono array di oggetti
4.10.1. length e arraycopy
length, var. istanza, dimensione dell'array, e' final (non modificabile) copia di un array: puo'
essere fatta con un ciclo oppure usando il metodo statico arraycopy:
System.arraycopy (from, fromStart, to, toStart, count)
Esempio:
double destinazione[] = new double[sorgente.length];
System.arraycopy(sorgente, 0, destinazione, 0, sorgente.length);
- 18 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
4.10.2. Array di oggetti
jButton[] bottoni;
// dichiarazione
bottoni = new jButton[10];
// ora contiene 10 puntatori a null
for (int i=0; i<bottoni.length; i++ )
bottoni[i] = new jButton();
// crea oggetto dentro l'array
4.10.3. Passaggio di array ad un metodo
public static double media(double[] data) {
if (data.length == 0) return 0;
double somma = 0;
for (int i=0; i< data.length; i++)
somma += data[i];
return somma / data.length;
}
Esempio di chiamata con array creato al volo (anonimo):
valMedio = media (new double[] {2.3, 2, 3, 4, 4.09, 8.09, 2.4, 1.55 });
4.10.4. Array dinamici
Gestione di array riempiti solo in parte (array dinamici):
• si usa una variabile di appoggio che tiene conto del numero di elementi effettivamente usati
(nome: nomearraySize)
• ogni volta che si aggiunge un elemento si aggiunge 1 a tale variabile
• quando si deve togliere un elemento si compatta l'array
• se si raggiunge il massimo si crea un array di dimensioni maggiori (il doppio ad esempio) e
si copia il vecchio nel nuovo aggiornando i riferimenti
double newData = new double[data.length * 2];
System.arraycopy(data,0, newData, 0, data.length);
data = newData;
// aggiorna riferimento
Una alternativa agli array dinamici e' data dalla classe Vector
4.10.5. Oggetti protected
i.e. jPanel nella classe padre La classe figlia puo' aggiungere oggetti all'oggetto protected
della classe padre; i pezzi aggiunti sono pero' suoi.
4.11. Package
Equivale ad una libreria, contiene piu' classi ed interfacce.
La struttura dei file in directory deve rispecchiare la struttura dei package.
Per rendere univoco il nome si parte da un URL o da un indirizzo e-mail (i.e.
luigife/libero/it/miopackage/miaclasse)
package PackageName;
public class NuovaClasse {
}
- 19 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
5. INTERAZIONE TRA GLI OGGETTI
5.1. Classi interne
Vedere esempio sotto grafica: Le classi interne.
5.2. Ereditarieta'
5.2.1. Classi astratte
Definizione: classe con almeno uno dei metodi definito astratto.
Uso:
• Classe padre astratta deve poter chiamare i metodi definiti nella classe figlia
• Classi che non devono poter essere istanziate (perche' sono prototipi di altre)
Regole:
Rectangle r;
Cuboid c;
// Cuboid extends Rectangle.
r = c;
// sempre ammesso
c = r; // vale solo se in realta' r era un Cuboid passato a Rectangle
5.2.2. Oggetti protected
i.e. jPanel nella classe padre La classe figlia puo' aggiungere oggetti all'oggetto protected
della classe padre; i pezzi aggiunti sono pero' suoi.
5.2.3. La classe Object
Metodo equals: si sovrascrive (overriding, non overloading) il metodo equals di Object in
modo da poter confrontare oggetti di tipo diverso.
Conviene sovrascrivere anche il metodo hashcode() di Object insieme a equals perche questi
lo usa: per la classe Object due oggetti sono uguali se hanno lo stesso hashcode.
5.3. Interfacce
Il concetto di interfaccia serve per supplire alla mancanza di ereditarieta' multipla in Java.
Una classe puo' ereditare da un'altra ed implementare una o piu' interfacce.
Una interfaccia definisce i metodi che una classe DEVE definire.
5.3.1. Uso delle interfacce: definizione di comportamenti
Quando oggetti di diverse classi devono presentare un comportamento omogeneo riguardo
ad una funzione trasversale.
Esempio:
public interface Comparable {
int compareTo(Object o)
}
NB: tutti i metodi definiti sono public di default e lo devono essere anche nelle classi che la
usano.
Uso:
public class Frazione extends Comparable {
- 20 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
...
public int compareTo(Frazione f) {
if (this.equals(f)) return 0;
if (this.isMinore(f)) return -1;
return 1;
}
public int compareTo(Object o) {
if (o istanceof Frazione) {
return compareTo((Frazione)o);
}
}
5.3.2. Uso delle interfacce: definizione di costanti comuni tra le classi
Esempio:
public interface Mesi {
int GENNAIO = 1;
int FEBBRAIO = 2;
}
• Uso 1: senza estendere Mesi: int mese = Mesi.GENNAIO;
• Uso 2: con extends Mesi: int mese = GENNAIO;
NB non e' necessaria la definizione di static final perche' lo sono di default.
Una interfaccia puo' estendere uno o piu' altre interfacce.
5.3.3. Esempio d'uso: casello di un ponte
Casello di un ponte: possono passare dei veicoli (ciascuno con la propria tariffa a seconda
della tipologia) o delle merci o delle persone.
Si crea l'interfaccia "Tariffabile" che prevede il metodo calcolaTariffa().
Nella classe Casello, che contiene una coda FIFO di oggetti di tipo Tariffabile, chiunque sia in
coda si chiama su di esso il metodo calcolaTariffa(), senza vedere di quale tipo di tratta.
In Veicolo (da cui ereditano Auto, Camion e Moto) il metodo calcolaTariffa e' dichiarato
abstract in modo da rendere la classe abstract e obbligare la definizione nelle classi che
ereditano.
- 21 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
5.3.4. Ereditarieta' multipla con Java
Rif: Koffmann, Wolfgang - Objects, astraction, data structures and design using Java version
5.0, Wiley, pag.156 e seguenti.
E' possibile con l'uso delle interfacce o con la composizione.
Esempio: Classi Studente e Lavoratore, serve la classe StudenteLavoratore.
Soluzione con le interfacce: si creano due interfacce StudenteInt e LavoratoreInt, le classi
Studente e Lavoratore ne implementano una ciascuna, StudenteLavoratore le implementa
entrambe.
Problema: non e' possibile definire attributi nelle interfacce.
Soluzione con la composizione (o delega): la classe StudenteLavoratore oltre ad
implementare le interfacce ingloba due oggetti di tipo Studente e di tipo Lavoratore. Occorre
mappare opportunamente i metodi delle interfacce.
public class StudenteLavoratore implements StudenteInt, LavoratoreInt {
private Studente s;
private Lavoratore l;
public StudenteLavoratore(String nome, String indirizzo,
String scuola, String corso,
String ditta, double stipendio) {
s = new Studente(nome, indirizzo, scuola, corso);
l = new Lavoratore(nome, inidirizzo, ditta, stipendio);
}
public
public
public
public
public
public
String
String
String
String
String
double
getNome() { return s.getNome();}
getIndirizzo() { return s.getIndirizzo();}
getScuola() { return s.getScuola();}
getCorso() { return s.getCorso();}
getDitta() { return l.getDitta();}
getStipendio() { return l.getStipendio();}
}
- 22 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
5.4. Composizione
Si riferisce alla proprieta' di passare gli oggetti come parametri ad altri oggetti.
- 23 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
6. COLLEZIONI DI OGGETTI
Ce ne sono di diversi tipi da utilizzare a seconda dell'uso:
Con Java 1.2 (e poi 1.4) e' stata definita un Java Collection Framework che contiene una
serie di interfacce nuove per la gestione delle collezioni e che sostituisce le vecchie:
• Vecchie:: Vector, HashTable, Enumeration
• Nuove:: Set, List, Map, Iterator
Conversione dalle vecchie alle nuove:
List list = new Vector();
Map map = new HashTable();
6.1. Criteri di scelta
Tipo
-------------array
ArrayList
Vector
HashMap
TreeMap
LinkedHashMap
HashSet
LinkedHashSet
dimensione
---------fissa
variabile
variabile
variabile
variabile
variabile
variabile
variabile
tipo elementi
------------prim. e ogg.
oggetti
oggetti
key+value
key+value
key+value
oggetti
oggetti
duplicati
---------si
si
si
non su key
non su key
non su key
no
no
indice
-----si
si
si
no
no
no
no
no
iteratori
--------no
si
si sincronized?
si
si
ordinata lenta
si
ordinata
si
si
ordinata
6.2. Iteratori
E' un design pattern per esplorare gli oggetti di una collezione che non fa riferimento a metodi
specifici del tipo di collezione.
import java.util.Iterator
Restituisce un Object, utilizzare un cast.
NOTA: Si chiede l'elemento successivo all'iteratore, non alla collezione.
Esempio:
Iterator it = myCollection.iterator();
while (it.hasNext()) {
Qualcosa qlc = (Qualcosa)it.next();
}
6.3. Modalita' di utilizzo
6.3.1. Uso degli array
Hanno dimensione fissa, funzionano sia con tipi primitivi che con oggetti, usano una sintassi
particolare rispetto alle normali classi.
Per percorrerlo:
for (int i = 0; i < array.length(); i++) {...}
6.3.2. Uso delle ArrayList
ArrayList: dimensione variabile, e' una lista di oggetti. Deriva da List.
- 24 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
import java.util.ArrayList;
Metodi:
• add(Object) aggiunge un elemento in coda
• Object get(int index) non rimuove l'oggetto dalla collezione
• int size()
• void remove(int index)
ATTENZIONE: la remove provoca la variazione degli indici dell'arrayList.
Esempio (con anche uso di iteratori)
class ArrayListExample {
private ArrayList lista;
private int postoLibero;
public ArrayListExample(){
lista = new ArrayList();
postoLibero = 1;
}
public void add(String dsc) {
lista.add(new QualcheElemento(postoLibero, dsc));
postoLibero++;
}
public void percorreListaConCiclo(){
int indice=0;
while (indice < lista.size()) {
QualcheElemento el = (QualcheElemento)it.get(indice);
...
indice++;
}
public void percorreListaConIteratori(){
iterator it = lista.iterator();
while (it.hasNext()) {
QualcheElemento el = (QualcheElemento)it.next();
...
}
}
public QualcheElemento getElemento(int chiave) {
// si spera che non ci siano stati remove, altrimenti non va
if (chiave>=1 && chiave < postoLibero) {
QualcheElemento el = (QualcheElemento) lista.get(chiave-1);
return el;
}
return null;
}
}
6.3.3. Uso dei Vector
Vector e' praticamente lo stesso che ArrayList.
Sono degli array (dinamici, cioe' con contatore degli elementi validi) nascosti nella classe
Vector: quando l'array e' pieno se ne crea uno piu' grande e si ricopiano i dati.
Se un record di una variabile Vector non mantiene il proprio valore ma lo cambia ad ogni
aggiunta di un nuovo record significa che e' stata definita static (cioe' e' una variabile di classe e
non di istanza)
Metodi:
• int capacity() capacita' del vettore (?)
• int size() numero di elementi contenuti
• Object elementAt(int index)
• void setElementAt(Object obj, int index)
• void insertElementAt(Object obj, int index) inserisce un elemento nella posizione index,
spostando i successivi in avanti di uno
- 25 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
• void addElement(Object obj) aggiunge in fondo al vettore
• void removeElementAt(int index) rimuove l'elemento; sposta indietro gli elementi successivi
• boolean removeElement(Object obj) rimuove l'elemento passato se presente restituendo
true, oppure restituisce false
• int indexOf(Object el) restituisce la prima posizione dell'oggetto el del vettore, -1 se non
trovato
6.3.4. Uso delle mappe
Una mappa e' una collezione di oggetti chiave/valore, in numero variabile.
Ciascun elemento e' una COPPIA di oggetti, cui si accede indicando la chiave e non l'indice
come invece accade negli ArrayList.
Sono usate se si conosce la chiave e si vuole conoscere il valore (sono "a senso unico").
Esempio di mappa: agenda (chiave nome, valore = stringa dei numeri di telefono)
Sottoclasse: HashMap Metodi:
• void(?) put (key, value)
• Object get (key)
Sottoclasse: TreeMap.
Si tratta di una mappa ordinata.
Esempio preso da CalEve - Gestione eventi del Calvino
TreeMap listaEventi;
Nel costruttore:
listaEventi = new TreeMap();
Inserimento di un elemento:
listaEventi.put(evento.getKey(), evento);
Ricerca di un intervallo di elementi e iterazione su di essi:
ATTENZIONE che se si specifica lo stesso valore di chiave per from e to
si ottiene l'insieme vuoto.
public String[] getEventi(int gg,int mm,int aaaa) {
String fromKey, toKey;
fromKey=""+(aaaa*10000+mm*100+gg);
if (gg==0) {
toKey=""+(aaaa*10000+mm*100+50);
}else{
toKey=""+(aaaa*10000+mm*100+gg+1);
}
SortedMap subList=listaEventi.subMap(fromKey, toKey);
sm=subList;
Iterator it = subList.entrySet().iterator();
int num = subList.entrySet().size(); // numero di elementi trovati
String[] eventi= new String[num];
int count=0;
Evento e = null;
while(it.hasNext()) {
String key =(String)((Map.Entry)it.next()).getKey();
//System.out.println("key = "+key+".");
e=(Evento)listaEventi.get(key);
eventi[count]=e.getDay()+" / "+mm+" / "+aaaa+" :
"+e.getDescr();
count++;
}
return eventi;
}
6.3.5. Uso dei Set (HashSet)
Sono insiemi di oggetti, esiste un unico item per ogni oggetto distinto (non ci sono duplicati).
Non e' garantito alcun ordine nell'esplorazione.
E' possibile utilizzare comunque Iterator.
- 26 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
- 27 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
7. FLUSSI
7.1. Scopo
Consentire la gestione di informazioni provenienti da fonti eterogenee, fra cui i supporti di dati
non volatili (e si parla di persistenza).
7.1.1. Flussi di dati, lettori e scrittori
Per la memorizzazione di dati si possono utilizzare:
• il formato testo (sequenza di caratteri: come codifica Java utilizza i codici Unicode a 32 bit,
il numero 12345 viene memorizzato in cinque caratteri '1' '2' '3' '4' '5' utilizzando in totale 10
byte).
In questo caso si parla di lettori (reader) e scrittori (writer).
• il formato binario (sequenza di byte: 12345 viene memorizzato in 4 byte contenenti 0 0 48
57) che e' piu' compatto ed efficiente ma non e' direttamente interpretabile con un editor di
testo.
Per i file binari si parla di flussi.
Tutte queste classi sono definite nel pacchetto java.io.
7.2. File di testo: Reader e Writer
Se si utilizza il formato testo si devono utilizzare le classi Writer e Reader (e le loro
sottoclassi): per leggere da disco si usa un oggetto FileReader, per scrivere FileWriter:
FileReader reader = new FileReader("input.txt");
Metodi: read , write:
questi sono gli unici metodi forniti per queste classi: il loro compito e' solo quelle di leggere o
scrivere singoli dati, non di analizzarli.
Se si vogliono fare operazioni piu' complesse e' possibile combinare queste classi con altre.
Quando si e' finito di utilizzare un file e' necessario chiudere il lettore o lo scrittore r.close().
7.2.1. Lettura di caratteri da file
La classe Reader ha il metodo read che legge un carattere alla volta (FileReader usa il
metodo sovrascritto per estrarre i caratteri da un file su disco): tuttavia il metodo read di fatto
restituisce un int in modo da poter segnalare sia che e' stato letto un carattere sia che e' stata
raggiunta la fine dell'input (attraverso il valore -1).
Si usa un cast per ottenere il carattere:
Reader r = ...
int next = r.read();
char c;
if (next != -1) c = (char)next;
7.2.2. Schema generale per la lettura
E' piu' conveniente leggere linee piuttosto che caratteri singoli. Essendo pero' la lunghezza di
una linea indefinita si usa una classe che si occupa di restituire stringhe di caratteri a partire da
un Reader: si usa cioe' un BufferedReader:
try{
BufferedReader reader = new BufferedReader(new FileReader("filename"));
String line = reader.readLine();
while(line!=null) {
- 28 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
//fa qualcosa con line
line= reader.readline();
}
reader.close();
} catch (FileNotFoundException e) {
// file non trovato
} catch (IOException e) {
// problemi durante la lettura o la chiusura
}
7.2.3. Schema generale per la scrittura
try{
FileWriter writer = new FileWriter("filename");
while( /* c'e qualcosa da scrivere */) {
...
writer.write(/* testo da scrivere */);
}
writer.close();
} catch (IOException e) {
// problemi durante le operaizoni sul file
}
7.2.4. Metodi di controllo
La classe File possiede dei motodi che possono essere utilizzati prima di aprire il file per
evitare di tentare con sicuro fallimento:
• exists()
• canRead()
Vanno utilizzati soprattutto con la lettura di file binari, con la scrittura di solito non e'
necessario che il file esista.
7.3. File binari: flussi
Se si utilizza il formato binario si parla di flussi e si utilizzano le classi OutputStream e
InputStream (e sottoclassi): per leggere da disco si usa la sottoclasse FileInputStream, per
scrivere FileOutputStream:
FileInputStream input = new FileInputStream("input.dat");
7.3.1. Lettura di bytes
Il metodo read legge int (16 bit), a noi servono byte (8 bit).
Si usa un cast per ottenere il carattere:
InputStream in = ...
int next = in.read();
byte b;
if (next != -1) b = (byte)next;
Utilizzare le eccezioni per gestire i molti casi di eventi inattesi (fine file, nome file errato,
impossibile creare file in scrittura..).
7.4. Esempio di gestione di flussi di dati: ConsoleReader
Utile per l'input da tastiera senza utilizzare l'alternativa delle finestre di dialogo (di Cay
Horstmann).
Scopo: leggere caratteri, numeri, linee da console.
1. L'oggetto System.in di tipo InputStream ha un solo metodo (read) per la lettura di byte.
Ogni carattere e' codificato in Java con due byte (Unicode).
- 29 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Terminologia:
• Flussi di input: (binari): leggono byte
• Lettori: (Reader) (testo): leggono caratteri
Convertiamo il flusso di input System.in in un oggetto reader:
InputStreamReader reader = new InputStreamReader(System.in);
2. I lettori leggono singoli caratteri: bufferizziamo in modo da leggere piu' caratteri e restituirli a
blocchi:
BufferedReader console = new BufferedReader(reader);
3. BufferedReader ha un metodo readLine
String input = console.readLine();
ATTENZIONE: occorre gestire in questo caso le eccezioni, usare un blocco
try { ...} catch..
4. conversione in numero:
int numero = Integer.parseInt(input);
Esempio di lettore da tastiera
public class ConsoleReader {
private BufferedReader reader;
public ConsoleReader (InputStream inStream) {
reader = new BufferedReader(new InputStreamReader(inStream));
}
public int readInt(){
String s = readLine();
return Integer.parseInt(s);
}
public double readDouble() {
String s = readLine();
return Double.parseDouble(s);
}
public String readLine() {
String inputLine = "";
try {
inputLine = reader.readLine();
}
catch(IOException e) {
System.out.println(e);
System.exit(1);
}
return inputLine;
}
}
7.4.1. Classe File
import.java.io.*;
Note: dato che possono generare eccezioni e' necessario specificare
"throws IOException" dopo main.
Dichiarazione:
File file=new File(nomefile);
Metodi:
public boolean canRead()
public boolean canWrite()
public boolean exists()
public String getCanonicalPath()
public String getName()
public boolean isDirectory()
- 30 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
public long length()
public String[] list()
vale solo per le directory
public String[] list(FilenameFileter f)
restituisce la lista dei file della directory che rispondono
al criterio specificato nel filtro passato (v. Dev n.58)
7.4.2. Classe FilenameFilter
import.java.io.*;
Note: (v. Dev 58) serve per filtrare i nomi dei file del metodo list della classe File.
7.4.3. Come creare una directory
Versione che funziona anche se mancano le directory padre: in pratica si fa la ricorsione
utilizzando StringTokenizer sul percorso da creare.
Il tentativo di metterlo in una classe e' mio.
src/mkdir.java
static class FileUtility {
/** Crea una directory creando pero' anche eventuali genitori se non esistono */
static void mkdir(String percorsoCompleto) {
StringTokenizer tokenDirectory = new StringTokenizer(percorsoCompleto, "\\");
StringBuffer stringaSottoDirectory = new StringBuffer("");
while (tokenDirectory.hasMoreElements()) {
stringaSottoDirectory.append(tokenDirectory.nextToken()).append("\\");
File sottoDirectory = new File(stringaSottoDirectory.toString());
if (!sottoDirectory.exists()) {
sottoDirectory.mkdir();
}
}
}
}
7.5. Flussi di oggetti - serializzazione
E' sufficiente aggiungere implements serializable all'interfaccia della classe.
C.Horstmann, Concetti di informatica e fondamenti di Java 2, p.583 (p.514 su Java 5).
Per essere serializzabile un oggetto deve contenere sottoclassi TUTTE serializzabili.
Ad esempio nel caso di un cliente che contiene un indirizzo
Vedi
class Cliente implements Serializable {
private String nome;
private Indirizzo ind;
}
la classe Indirizzo deve essere anch'essa serializzabile (se non lo fosse vedi capitolo
successivo).
Uso
public class Test {
public static void main(String[] args){
Cliente c;
File f = new File ("Clienti.dat");
if (f.exists()) {
ObjectInputStream in = new ObjectInputStream(
new FileInputStream(f));
c = (Cliente)in.readObject();
} else {
c = new Cliente(...);
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 31 -
LF Java Handbook
}
c.add(...);
ObjectOutputStream out = new ObjectOutputStream (
new FileOutputStream(f));
out.writeObject(c);
out.close();
}
}
7.5.1. Serializzazione di oggetti che non implementano Serializable
Il problema si pone qunado un oggetto che si intende serializzare contiene delle variabili
istanza di classi non serializzabili.
E' il caso, ad esempio, di alcuni oggetti geometrici che non sono serializzabili a causa della
dimenticanza dei progettisti.
La soluzione e' di prevedere dei metodi che salvano le singole istanze degli oggetti
utilizzando esplicitamente la parola chiave transient.
Vedi C.Horstmann, Concetti di informatica e fondamenti di Java 2, p.586 (p.516 su Java 5).
Attenzione: si devono dichiarare due metodi PRIVATI appositi che salvino i dati delle variabili
non serializzabili e li ripristinino alla fine.
7.5.2. Serializzazione di oggetti tramite JavaBean
A partire da Java 1.4 e' statp introdotto un nuovo metodo per la persistenza di oggetti, che
produce dei file XML e che per questo viene chiamata "long term bean persistence".
Vedere doc di Java, classe java.Beans.XMLEncoder.
E' utilizzata ad esempiodal programma Violet di K. Horstmann.
7.6. Accesso casuale
Vedi C.Horstmann, Concetti di informatica e fondamenti di Java 2, p.587 (p.505 in Java 5)
7.6.1. Classe RandomAccessFile
import.java.io.*;
Dichiarazione:
RandomAccessFile file=new RandomAccessFile(nomefile,"rw");
Metodi:
public void close()
public long getFilePointer()
restituisce la posizione corrente all'interno del file
public long length()
dimensione del file
public final byte readByte()
public final String readLine()
public void seek(long n)
posiziona il puntatore alla byte n del file
con n che vale RAfile.lenght si va a finefile
public final void writeBytes(String s)
scrive sul file s a partire dalla posizione corrente.
Sovrascrive se non siamo a fine file.
7.7. Flussi su rete di telecomunicazioni
7.7.1. Esecuzione di script su server con passaggio di un solo parametro
Non sono necessarie particolari attenzioni: e' sufficiente passare il valore del parametro di
seguito all'URL preceduto da un ?.
Frammento di codice; per URL reader vedi paragrafo subito dopo
void buildPanel(String cgi, String par) {
- 32 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
String url=cgi+"?"+par;
JTextArea text = new JTextArea();
try {
URLReader ur= new URLReader(url);
String line;
while ((line=ur.readLine())!=null) {
System.out.println(line);
text.append(line+"\n");
}
System.out.println("End.");
} catch (Exception e) {
text.append("Exception on: " + cgi +" parameter "+par+ ".\n");
text.append("Exception " + e + ".\n");
}
7.7.2. Esecuzione di script su server con passaggio di parametri: uncgi
Sul server deve essere installato uncgi (io ho versione 1.11).
Per Struttura delle dir e per un esempio di uncgi script vedi manuale WebServer.
Si deve aprire un URL come connessione e inviare i parametri con il metodo get.
Esempio
import java.util.*;
import java.io.*;
/**
* Read from a URL with a uncgi script.
* Send parameters on command line (GET method)
*
* @author L. Ferrari - [email protected]
* @version 1.0 21.9.2004
* @history 1.0 Versione originale
*/
public class ProcessConfigReader {
public ProcessConfigReader(){
}
public static void main(String arg[]) {
String urlString;
if (arg.length == 0) {
urlString = "http://l3/cgi-bin/uncgi/testlf.cgi";
}else{
urlString=arg[0];
}
HashMap par= new HashMap();
par.put("par1","prova1");
par.put("par2","/tmp/esempio.txt");
par.put("par3","34.7890");
try {
URLReader ur= new URLReader(urlString,par);
String line;
while((line=ur.readLine())!=null){
System.out.println("Read: "+line);
}
System.out.println("End.");
} catch (FileNotFoundException e) {
System.out.println("File: " + arg[0]+File.separator+arg[1]+ " not found.");
} catch (IOException e) {
System.out.println("Error on file: " + urlString + ".\n"+e);
} catch (Exception e) {
System.out.println("URLReader: Exception on: " + urlString +"\n"+e);
}
System.exit(0);
}
}
----------------------------------------------------------------------------------------import java.net.*;
import java.io.*;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
/**
* Generic and specific URL reader.<p/>
* Contructors open the URL and send to it parameters if necessary.
*
- 33 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
* @author L. Ferrari - [email protected]
* @version 1.0 7.10.2004
* @history 1.0 Versione originale
*/
public class URLReader {
private BufferedReader in;
private URL url;
private HttpURLConnection urlConn;
/** Open a URL and a buffered reader for it.
* @param urlString input URL.
*/
public URLReader(String urlString) throws Exception {
this.url= new URL(urlString);
urlConn=(HttpURLConnection)this.url.openConnection();
urlConn.setDoInput(true);
urlConn.setUseCaches(false);
urlConn.setAllowUserInteraction(true);
in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
}
/** Open a URL who is a cgi or uncgi script and put it a list of parameters.<p/>
* Parameters will be sended with GET method, into par1=val1&par2=val2&par3=val3... form.
*
* @param urlString source URL
* @param par map of parameters. They will be encoded before send to URL.
*/
public URLReader(String urlString, Map par) throws Exception {
this.url= new URL(urlString);
urlConn=(HttpURLConnection)this.url.openConnection();
urlConn.setDoOutput(true);
PrintWriter out = new PrintWriter(urlConn.getOutputStream());
Set keyValues = par.entrySet();
Iterator it = keyValues.iterator();
String mapStr="\n";
while(it.hasNext()) {
Map.Entry en=(Map.Entry)it.next();
out.print((String)en.getKey()+"="+
java.net.URLEncoder.encode((String)en.getValue(),"ISO-8859-1"));
if (it.hasNext()) out.print("&");
mapStr+= "
" + en.getKey()
+ " = "+en.getValue()+ "\n";
}
System.out.print("DEBUG: URLReader: properties:"+mapStr);
out.close();
in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
}
/** Close the URL
*/
public void close() throws Exception{
in.close();
}
/** Print URL content on standard output
*/
public void printOut() throws IOException{
String line;
while ((line=in.readLine())!=null)
System.out.println(line);
}
/** Read a line from URL
* @return a line read from URL or null if no data found.
*/
public String readLine() throws IOException{
return in.readLine();
}
}
- 34 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
8. APPLET
8.1. Caratteristiche
Le applet sono come dei programmi grafici ma vengono eseguite all'interno di un browser
Web.
Il codice di una applet e' conservato in un server Web (a livello di bytecode) e viene scaricato
nel browser quando si accede alla pagina che contiene l'applet.
Vantaggi:
• non e' necessario essere sul proprio PC per eseguirla
• puo' essere aggiornata senza operazioni presso l'utente: si aggiorna solo il codice sul
server (comodo ad esempio nelle Intranet)
• e' indipendente dal sistema operativo
Svantaggi:
• deve essere scaricata dalla rete ogni volta
8.2. Protezione
Questo metodo potrebbe prestarsi alla diffusione di virus su tutti i computer che accedono alla
pagina contenente la applet.
Per evitarlo le applet hanno due meccanismi di protezione:
• si possono firmare
• si possono eseguire con diversi privilegi di sicurezza
Per impostazione predefinita una applet viene eseguita dalla Java Virtual Machine con
privilegi molto limitati:
• puo' visualizzare informazioni e ricevere input da parte dell'utente
• non puo' eseguire programmi sul pc locale
• non puo' effettuare operazioni di I/O (lettura/scrittura su file) sul pc locale
• non puo' effettuare chiamate verso metodi nativi (cioe' che si interfacciano direttamente con
l'hardware del pc)
• non puo' stabilire connessioni con altre macchine oltre a quella da cui e' stata scaricata
Esempio: non funzionano il taglia/incolla da TextArea della Applet (mentre va se lo stesso
programma e' lanciato come Frame).
8.3. Struttura del file HTML per la chiamata di applet
<HTML>
<HEAD>
<TITLE>EsempioApplet Applet</title>
</head>
<body>
<p> ESEMPIO DI APPLET</p>
<APPLET
CODE="EsempioApplet.class"
ARCHIVE="libreria1.jar,libreria2.jar"
ORACLE_SID="T"
WIDTH=500
HEIGHT=500
>
Testo alternativo alla applet se il browser non e' abilitato
<PARAM NAME="Squadra" VALUE="Sampdoria">
</APPLET>
</body>
</html>
- 35 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
NOTE:
• il testo e' utilizzato solo nel caso che il browser non sia in grado di gestire le applet.
• archive: e' necessario che nella parola chiave archive ci siano tutti i file jar da cui occorre
prendere le classi, separati da virgole.
• archive: non e' possibile usare due tag archive separati.
• archive: Bluej versione 1.3.5 ha problemi con la crezione dei .jar se si sono cambiati i nomi
delle classi. Fare attenzione che non rimangano le vecchie. Nel dubbio cancellare i .class e
ricostruirli prima di metterli nei .jar.
8.4. Scrittura del codice
• nella dichiarazione della classe si aggiunge "extends Applet"
• non esiste metodo main
• sono previsti cinque metodi di gestione, con comportamento predefinito ma che possono
essere riscritti.
init, eseguito una sola volta all'inizio
start, eseguito subito dopo init e dopo ogni sospensione del
funzionamento, ad esempio per il passaggio ad un'altra finestra
paint, eseguito ogni volta che c'e' necessita' di ridisegnare
l'applet (ad es. dopo ridimensionamento finestra)
stop, eseguito ogni volta che l'utente esce dalla pagina Web che
contiene le applet
destroy, richiamato del web browser quando l'applet puo' essere
rimossa completamente dall'applicazione
8.5. Passaggio di parametri ad una applet
Consentono di cambiare il comportamento della applet senza doverla ricompilare: possono
essere specificati nella pagina HTML che contiene la chiamata alla applet:
<APPLET CODE="AppletProva" WIDTH=300 HEIGHT=140>
<PARAM NAME="Squadra" VALUE="Sampdoria">
<PARAM NAME="Rosso" VALUE="1.0">
</APPLET>
e possono essere letti nel codice con getParameter(), ad esempio nel metodo init della
applet:
String squadra = getParameter("Squadra");
float rosso = Float.parseFloat(getParameter("Rosso"));
String parametro = get Parameter("IMAGESOURCE");
imageSource = (parametro == null) ? getDocumentBase() : new URL..;
8.6. Classe che fa da applet e da applicazione grafica
In pratica e' sufficiente aggiungere il metodo main.
public class AppletEFrame extends Applet {
...
public static void main(String args[]){
Frame f = new Frame("Titolo del frame");
AppletEFrame aef = new AppletEFrame();
aef.init();
aef.start();
f.add("Center", aef);
f.setSize(800,600);
f.setVisible(true);
}
- 36 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Ci andrebbero aggiunti anche i listener per la chiusura della finestra.
E' possibile fare lo stesso con JApplet e JFrame:
public class JAppletEJFrame extends JApplet {
...
public static void main(String args[]){
JAppletEJFrame a = new JAppletEJFrame();
JFrame f = new JFrame("Titolo del frame"); // "Applet: "
+a.getClass().getName();
f.setSize(800,600);
f.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
System.exit(0); } });
f.getContentPane().add(a);
a.init();
f.setVisible(true);
}
Vedere anche altri esempi nel Java Tutorial e il libro Java di Camagni-Nikolassay (UD6, p.205).
8.7. Tips sulle applet
8.7.1. Memorizzazione di dati su stream (condivisione di dati tra applet)
Dalla versione 1.4 di Java e' possibile memorizzare dati di una applet su degli stream di
caratteri, e lo stesso stream puo' essere letto da altre applet SULLA STESSA MACCHINA.
Una applet puo' aprire un numero indefinito di stream e ognuno di essi e' accessibile
mediante una chiave.
Per un esempio vedere Sun: Core Java Technigies Tips del 14 marzo 2006, provato sotto
Luigi/Java/Sun (classe StreamsApplet).
L'ho provato lanciando due finestre del browser e gli stream creati su una era modificabili
sull'altra. Ci possono essere problemi di sincronizzazione.
Gli streams sono accessibili fino a che almeno una delle applet rimane viva.
8.7.2. Installazione di applet su Web Server (TO DO)
8.7.3. Installazione su login diversa da quella del Web Server (TO DO)
8.7.4. Come visualizzare un file sul server (TO DO)
8.7.5. Come lanciare comandi sul server (TO DO)
8.7.6. Visualizzazione del nome dell'host
Puo' essere inserito come informazione nell'help della applet.
import java.net.URL;
String host=getCodeBase().getHost();
Attenzione che se si puo' lanciare anche come applicazione non puo' leggere il valore (da'
exception).
8.7.7. Come aprire una nuova finestra
Esempio (CCSapiControlCenter)
JDialog f = new JDialog();
f.setTitle(getSelectedProcess().name+" configuration");
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 37 -
LF Java Handbook
f.setModal(true);
JComponent c = (JComponent) f.getContentPane();
c.add(new ConfigPanel(getSelectedProcess().name,
getSelectedProcess().getConfig()), BorderLayout.NORTH);
f.pack();
f.setVisible(true);
repaint();
8.7.8. Come ridisegnare una nuova finestra pop-up su se stessa (TO DO)
8.7.9. Come esportare dati da una applet (TO DO)
8.7.10. Debug e Log di una applet
Scrivere su System.out non e' una soluzione accettabile, almeno in fase di rilascio del
programma. E' possibile condizionarle con una variabile:
if (debug) System.out.println(...)
Altra soluzione e' utilizzare una classe per il log da attivare a livello di parametro della applet.
Altra soluzione e' utilizzare la barra di stato (brutta soluzione perche' non e' garantiro
funzioni).
8.7.11. Messaggi sulla barra di stato
Si usa il metodo showStatus(String s).
Non utilizzarlo per inserire informazioni cruciali, ma solo informative:
potrebbero essere sovrascritte dal browser.
- 38 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
9. GRAFICA
9.1. Gestione degli eventi
NOTA: vedi anche il pattern Observer e il pattern Command.
I programmi moderni consentono all'utente di avere il controllo del flusso del programma.
Esempi di strumenti di controllo del flusso che possono generare degli eventi: pressione di
tasti, clic del mouse, pressione di pulsanti.
In Java e' il gestore delle finestre di Java che gni volta che accade un evento significativo
invia una comunicazione al programma. Il numero di eventi puo' essere enorme (es. evento
"movimento del mouse").
Il programma, per non essere sommerso da segnalazioni di eventi non significativi, indica
quali eventi gradisce ricevere grazie all'installazione di oggetti "intercettatori di eventi" (event
listener). In piu' esistono "tipi" diversi di eventi (eventi di tastiera, di movimenti e di clic del
mouse): per ogni tipo ci sono diverse classi di event listener.
Per installare un listener occorre conoscere l"origine" dell'evento:
essa e' il componente dell'interfaccia utente che genera un determinato evento.
Esempi:
un pulsante e' l'origine degli eventi per il clic del mouse, una voce di menu' e' l'origine per un
evento di selezione di menu', una barra di scorrimento e' l'origine per un evento di regolazione
della barra di scorrimento.
Sono coinvolte tre classi:
• la classe evento: per il mouse e' MouseEvent, che puo' indicare le coordinate x,y del
puntatore del mouse e quale pulsante del mouse e' stato premuto;
• la classe dell'intercettatore (listener): per il clic del mouse deve essere una classe che
implementa l'interfaccia MouseListener.
Questa interfaccia ha molti metodi, che vengono chiamati quando si preme un pulsante del
mouse, quando lo si rilascia...
Ciascuno di questi metodi ha un parametro MouseEvent.
• l'origine dell'evento. E' il componente che genera l'evento del mouse: nel nostro caso e' la
applet, nella cui area occupata dello schermo l'utente puo' fare clic con il mouse. Dobbiamo
dire alla applet quali listener del mouse bisogna avvertire quando si verifica un evento del
mouse.
Tutte le classi evento sono sottoclassi di EventObject che ha un metodo getSource che
restituisce l'oggetto che ha generato l'evento. Le sottoclassi hanno i loro metodi per descrivere
ulteriormente l'evento: ad esempio MouseEvent ha i metodi getX e getY.
Diagramma di ereditarieta'
EventObject
|
AWTEvent
/
\
ActionEvent
ComponentEvent
/
\
InputEvent
WindowEvent
/
\
MouseEvent
KeyEvent
La parte piu' complessa e' individuare il listener: per esempio il listener del mouse deve
implementare l'interfaccia MouseListener e i cinque metodi seguenti:
public interface MouseListener {
- 39 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
void mouseClicked (mouseEvent e);
chiamato quando si e' fatto clic su un componente
void mouseEntered (mouseEvent e);
chiamato quando il cursore del mouse entra in un componente
void mouseExited (mouseEvent e);
chiamato quando il cursore del mouse esce da un componente
void mousePresseded (mouseEvent e);
chiamato quando un pulsante del mouse e' stato premuto
void mouseReleased (mouseEvent e);
chiamato quando un pulsante del mouse e' stato rilasciato
}
La nostra classe sposta una ellisse disegnata dalla applet nella posizione dove si fa clic con il
mouse.
Possiamo mettere la classe che implementa il listener in due punti, pur rimanendo nello stesso
file:
a. come classe separata dalla classe applet: va bene se non dobbiamo accedere a variabili
istanza della applet (ad esempio se volessimo solo spiare e stampare su System.out)
class MouseSpy implements MouseListener {
void mouseClicked (mouseEvent e) {
System.out.println(" Clic: x = " + e.getX()
}
void mouseEntered (mouseEvent e) {
System.out.println("Enter: x = " + e.getX()
}
void mouseExited (mouseEvent e) {
System.out.println(" Exit: x = " + e.getX()
}
void mousePresseded (mouseEvent e) {
System.out.println("Press: x = " + e.getX()
}
void mouseReleased (mouseEvent e) {
System.out.println(" Rel.: x = " + e.getX()
}
}
public class MouseSpyApplet extends Applet {
public MouseSpyApplet () {
MouseSpy listener = new MouseSpy();
addMouseListener(listener);
}
}
+ " y = " + e.getY());
+ " y = " + e.getY());
+ " y = " + e.getY());
+ " y = " + e.getY());
+ " y = " + e.getY());
b. come classe "interna" alla classe applet: questa soluzione e' necessaria ogni volta che
dobbiamo accedere a delle variabili istanza della classe applet.
E' la soluzione usata nell'esempio.
Per evitare di dover implementare tutti e cinque i metodi anche se alcuni non ci interessano,
conviene utilizzare una classe adapter che semplicemente implementa i 5 metodi come "non
fare niente":
Definizione della classe MouseAdapter
// e' definita nel pacchetto java.awt.event
public class MouseAdapter implements MouseListener {
void mouseClicked (mouseEvent e) {}
void mouseEntered (mouseEvent e) {}
void mouseExited (mouseEvent e) {}
void mousePresseded (mouseEvent e) {}
void mouseReleased (mouseEvent e) {}
}
9.1.1. Esempio completo
import
import
import
import
import
java.applet.Applet;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.geom.Ellipse2D;
java.awt.event.*;
- 40 -
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
public class GestioneEventi extends Applet {
private Ellipse2D.Double puntatore;
private static final double DIAMETRO = 15;
public GestioneEventi() {
puntatore = new Ellipse2D.Double (0,0, DIAMETRO, DIAMETRO);
// intercettatore degli event del mouse
MouseClickListener l = new MouseClickListener();
addMouseListener(l);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.draw(puntatore);
}
// definizione dela classe interna per la gestione del mouse
private class MouseClickListener extends MouseAdapter {
public void mouseClicked (MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
puntatore.setFrame(mouseX - DIAMETRO/2, mouseY - DIAMETRO/2,
DIAMETRO, DIAMETRO);
repaint();
}
}
9.2. Classi interne
Si noti che la classe interna accede alla variabile istanza "puntatore" della classe esterna
(perche' non ha variabili istanza che si chiamano cosi').
La classe esterna costruisce un oggetto della classe interna e lo aggiunge come intercettore
degli eventi di mouse.
L'oggetto della classe interna ("l" nel nostro caso) si ricorda dell'oggetto che lo ha costruito: in
via eccezionale il metodo della classe interna ha il privilegio di accedere a variabili istanze
PRIVATE della classe esterna: sembra pericoloso ma in realta' il pericolo c'e' con le variabili
istanza PUBBLICHE, cui tutti possono accedervi, mente qui si tratta sempre della stessa classe.
Il metodo setFrame non produce effetti sulla visualizzazione sullo schermo, semplicemente
aggiorna l'oggetto Java che contiene la posizione del cerchietto sullo schermo.
Dobbiamo ridisegnare: non possiamo utilizzare il metodo paint() perche' ci servirebbe un
oggetto Graphics che non abbiamo: potremmo procurarcelo ma non sarebbe comunque una
buona soluzione, perche' non si deve chiamare direttamente il metodo paint() per non interferire
con il gestore delle finestre.
Conviene invece dire alla applet di ridisegnare se' stessa, alla prima occasione possibile: si
usa il metodo repaint(), che a sua volta chiama il metodo paint() al momento opportuno e con
un oggetto Graphics adatto.
La chiamata a repaint() e' fatta nel metodo mouseClicked della classe MouseClickListener:
ovviemente tale classe non ha il metodo repaint(), quindi il compilatore lo cerca nella classe
esterna, dove lo trova (ereditato dalla superclasse Component), e lo chiama.
Su quale oggetto e' stato invocato il metodo? su quello della classe esterna (cioe' l'applet che
ha costruito il listener).
Le classi interne sono piuttosto particolari, molto utili per intercettare eventi ma difficilmente
utilizzate per altri scopi.
Conviene utilizzarle utilizzando lo schema generale.
9.3. Come combattere lo sfarfallio delle animazioni
Vedere articoli - Ridefinizione del metodo Update - Doppio Buffering
- 41 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
10. SWING
E' una alternativa a AWT, con diversa filosofia: ridisegna i componenti nello stesso modo
sotto tutti gli ambienti, mentre AWT usa le primitive del sistema operativo.
Il doppio buffering e' incluso.
10.1. Classi
(v. 9.4)
10.1.1. JOptionPane
Esempi di uso
JOptionPane.showMessageDialog(null,"Messaggio da mostrare",
JOptionPane.INFORMATION_MESSAGE);
String input = JOptionPane.showInputDialog("Scegli il valore da assegnare alla cella");
if (input== null) return;
if (Character.isDigit(input.charAt(0))) {
int valore=Character.digit(input.charAt(0),10);
target.setValore(valore);
}else{
JOptionPane.showMessageDialog(null,"messaggio", "Titolo",
JOptionPane.WARNING_MESSAGE);
}
TIPS:
• nel metodo showInputDialog e' necessario gestire la scelta "Annulla" verificando che la
stringa non sia nulla (vedi esempio sopra).
Esempio di messaggio di warning su una operazione, i.e in una actionPerformed
int ret = JOptionPane.showConfirmDialog(null,
"Sei sicuro di voler uscire\ndal
programma?","Esci",JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
if (ret == 0) // 0 per si, 1 per no
System.exit(0);
10.1.2. JFrame
E' la classe principale per la crezione di un aapplicazione grafica.
Esempio: come creare un frame che testi un componente grafico.
public class JXXX extends JPanel {
public JXXX () {
setPreferredSize(new java.awt.Dimension(400,400));
setMinimumSize(new java.awt.Dimension(400,400));
...
}
...
public static void main(String [] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
// alternativa a implememtare il listener.
f.setTitle("Test del componente JXXX");
f.setSize(600,480);
f.setForeground(java.awt.Color.blue);
// Per specificare il comportamento in chiusura:
f.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
System.exit(0);
// nel caso di piu' sorgenti per la chiusura
// utilizzare la chiamata di un metodo
}
});
JXXX c = new JXXX();
- 42 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
f.getContentPane().add(c);
f.pack();
f.setVisible(true);
// adatta alle dimensioni del contenuto
}
}
Note sui metodi:
• getContentPane: Serve per aggiungere componenti al frame, che non possono essere
aggiunti direttamente con add.
• pack: Adatta la finestra ai componenti che ci sono dentro, forse anche se si e' chiamato
setSize() (da confermare).
• setVisible: Mostra il frame. Precedentemente si utilizzava show, deprecato da java 5.
Main che lancia un JFrame Per evitare deadlock con swing e awt non conviene eseguire
semplicemente la new ma utilizzare un thread apposito (v. Winder-Roberts Developing Java
Software, p.334).
public class AJFrame extends JFrame {
...
public static void main(String [] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {new AJFrame();}
});
}
}
10.1.3. Menu': JMenuBar, JMenu, JMenuItem, JPopupMenu
Per la costruzione di menu' si utilizzano diverse classi:
• JMenuBar: una barra di menu' che puo' essere aggiunta al frame corrente oppure in un
qualsiasi contenitore (i.e. JPanel).
• JMenu: un menu' con piu' voci ed eventuali sottovoci. Per aggiungere un separatore
utilizzare
JMenu m
...
m.addSeparator();
• JMenuItem: una voce di menu (puo' essere sostituito da una Action). Consente di definire
alcune proprieta' dell'item in un colpo solo (ad esempio icona, tasto accelleratore etc.).
• JMenuPopup: un menu' che puo' essere aggiunto ad un qualsiasi componente ed essere
attivata, ad esempio, con il click dx del mouse.
Esempio d'uso in progetto sudoku; doc in Fondumental of swing: Part I, short course
(stampato).
Tips: Per aggiungere uno spazio tra un menu' a discesa e il successivo utilizzare:
JMenuBar menuBar = new JMenuBar();
menuBar.add(createMenu("Menu1"));
menuBar.add(Box.createHorizontalGlue());
menuBar.add(createMenu("Help"));
// separatore
Attenzione: una volta che un menu' e aggiunto ad un JMenuBar non puo' essere utilizzato in
altri punti.
Per poter fare la stessa azione con piu' tipi di interfaccia (bottoni, menu, ...) si devono
utilizzare le action (vedi esempio nella parte di grafica).
10.1.4. JButton
- 43 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Vedi esempio Grafica/ButtonDemo.java.
ATTENZIONE: per gestire i menu Popup non si puo' utilizzare il metodo
JPopupMenu.setInvoker() ma occorre definire una classe interna listener come nel seguente
esempio (preso da sudoku).
...
private JButton button;
private JPopupMenu popupMenu;
public AJPanel() {
...
button.setHorizontalAlignment(SwingConstants.CENTER);
button.setText(""+cella.getValore());
button.setBackground(Color.WHITE);
button.setEnabled(false);
button.setAction(new CellaAction("CLICK",null, this));
button.setBorder(null);
popupMenu = new JPopupMenu();
popupMenu.add(new JMenuItem(new AnAbstractAction("azione1", null, this));
popupMenu.addSeparator();
popupMenu.add(new JMenuItem(new AnAbstractAction("azione2", null, this));
// non va: popupMenu.setInvoker(button);
MouseListener popupListener = new PopupListener(popupMenu);
button.addMouseListener(popupListener);
this.add(button);
update();
}
...
/** Classe interna presa dal tutorial di Java per gestire il popup su un bottone
* che altrimenti non funziona.
*/
class PopupListener extends MouseAdapter {
JPopupMenu popup;
PopupListener(JPopupMenu popupMenu) { popup = popupMenu; }
public void mousePressed(MouseEvent e) { maybeShowPopup(e); }
public void mouseReleased(MouseEvent e) { maybeShowPopup(e); }
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
/** Classe interna per la gestione delle azioni effettuate sulla cella.
*/
class AnAbstractAction extends AbstractAction {
private AComponent target;
public AnAbstractAction(String name, Icon icon, Component comp) {
putValue(Action.NAME, name);
putValue(Action.SMALL_ICON, icon);
target = (AComponent)comp;
}
public void actionPerformed(ActionEvent evt) {
String name=(String)getValue(Action.NAME);
System.out.println("AnAbstractAction: Action "+name+" command:
"+evt.getActionCommand());
// popupMenu:
if (name.equalsIgnoreCase("azione1")) {
String input = JOptionPane.showInputDialog("Inserisci un numero intero");
if (input== null) return;
if (Character.isDigit(input.charAt(0))) {
int valore=Character.digit(input.charAt(0),10);
target.setValore(valore);
}else{
JOptionPane.showMessageDialog(null,"Valore non ammesso! Riprova!",
"Valore errato",
- 44 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
JOptionPane.WARNING_MESSAGE);
}
}else if (name.equalsIgnoreCase("Azione2")) {
JOptionPane.showMessageDialog(null,"Ciao!", "Titolo: ciao!",
JOptionPane.INFORMATION_MESSAGE);
// Click sul bottone
}else if (name.equalsIgnoreCase("CLICK")) {
System.out.println("CellaAction: Click on "+ target.getId() + " > "
+target.getValore());
}
target.update();
// aggiorna componente che ha attivato l'action
}
}
10.1.5. JFileChooser
Vedi esempio in GiteLF.
10.1.6. JTable
Implementa il pattern MVC.
tips:
• setPreferredSize(new java.awt.Dimension(400,400));
Vedi esempi.
10.1.7. Layout
Si applicano ad esempio a Jpanel.
Predefiniti:
BorderLayout
FlowLayout
GridLayout
10.1.8. JList
Una JList e' un elenco di voci, selezionabile.
JList filtrate Per filtrarle e' possibile utilizzare un filtro come descritto un Sun, Core Java
Technologies Tips del 14 Dicembre 2005 (fatto sotto Jdk 1.5, che ho portato sotto JdK 1.4.2
sotto Dell8500/Users/Luigi/Java/Sun, classi FilteringJList e il frame Filters).
Con il filtro l'utente digita una stringa e il modello in autometico mantiene solo le voci che
contengono la stringa utilizzata come filtro.
- 45 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
11. THREAD
I thread sono utilizzati in ogni programma Java.
Un thread e' un singolo algoritmo sequenziale all'interno di un programma.
Esso ha un inizio, una serie di istruzioni eseguite in sequenza e una fine.
Un thread non puo' essere eseguito in maniera indipendente, ma solo all'interno di un
programma.
In un programma che richiede un unico flusso del programma non e' necessario preoccuparsi
esplicitamente del thread: esso viene creato e gestito dalla JVM (Java Virtual Machine) in
maniera trasparente ed automatica.
Uno dei punti di forza del linguaggio Java e' che e' possibile programmare piu' thread
all'interno di un unico programma in maniera molto semplice.
Esempio: un browser web puo' eseguire il dowload di un file da un sito e
contemporaneamente visualizzare un altro sito, senza aspettare che abbia finito il download.
La JVM esegue sempre piu' thread simultaneamente, i Deamon threads: ad esempio c'e un
thread che gestisce la garbage collection, un altro resta in attesa degli eventi del mouse ed un
altro di quelli della tastiera.
E' possibile da un programma modificare il compertamento di questi thread.
Attenzione con l'uso del pattern Singleton (Metsker, Pattern design, p.83)
11.1. Eventi di un thread
Un thread ha un suo ciclo di vita ben definito:
• start: inizio
• stop: fine del ciclo di vita
• pause: puo' stare fermo per un periodo di tempo
• wait: attesa di un evento
• run: puo' scambiare informazioni con altri thread.
11.2. Definizione del metodo run()
Il metodo run() definisce il comportamento di un thread.
Per implementarlo ci sono due strade possibili:
• 1.: estendere la classe java.lang.thread
• 2.: implementare l'interfaccia java.lang.Runnable
11.2.1. Estensione della classe Thread
La classe Thread ha un metodo run() che deve essere ridefinito; si crea una nuova istanza
della classe con new(); si eseguo una istanza chiamando il metodo start() che a sue volta
chiama il metodo run().
Esempio
package ProcessiConcorrenti;
/**
* <p>Title: Corso di Java -</p>
* <p>Description: esempio di uso dei thread estendendo la classe thread</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: </p>
* @author Luigi Ferrari
* @version 1.0 del 22.3.2003
*/
public class Contatore extends Thread {
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 46 -
LF Java Handbook
private int inizio;
private int fine;
public Contatore(int da, int a) {
this.inizio=da;
this.fine=a;
}
public void run() {
System.out.println(this.getName()+ " partito...");
for (int i=inizio; i<= fine; i++) {
System.out.println(this.getName() + ": " + i);
//attende un tempo casuale inferiore al secondo
try {
sleep((int) Math.random() * 1000); // max 1 sec
} catch(InterruptedException e) {}
}
System.out.println(this.getName()+ " finito.");
}
public static void main(String[] args) {
Contatore contatore1 = new Contatore(1,10);
Contatore contatore2 = new Contatore(20,30);
contatore1.start();
contatore2.start();
}
}
11.2.2. Implementazione dell'interfaccia Runnable
Occorre:
• implementare il metodo run() nella classe;
• creare una istanza della classe con new();
• creare una nuova istanza della classe Thread con new(), passando come parametro
l'istanza della classe creata
• invocare il metodo start() dell'oggetto Thread creato, provocando la chiamata di run()
Il vantaggio di implementare l'interfaccia Runnable e' che la classe puo' ereditare da qualsiasi
altra classe, aumentando la liberta' del programmatore.
Esempio
package ProcessiConcorrenti;
/**
* <p>Title: Corso di Java - Processi concorrenti</p>
* <p>Description: uso dei thread implementando la interfaccia runnable
* </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: </p>
* @author Luigi Ferrari
* @version 1.0
*/
public class ContatoreRunnable implements Runnable {
private int inizio;
private int fine;
public ContatoreRunnable(int da, int a) {
this.inizio=da;
this.fine=a;
}
public void run() {
System.out.println(Thread.currentThread() + " partito...");
for (int i=inizio; i<= fine; i++) {
System.out.println(Thread.currentThread() + ": " + i);
//attende un tempo casuale inferiore al secondo
try {
Thread.currentThread().sleep((int) Math.random() * 1000);
// max 1 secondo di attesa
} catch(InterruptedException e) {}
- 47 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
}
System.out.println(Thread.currentThread()+ " finito.");
}
public static void main(String[] args) {
ContatoreRunnable contatore1 = new ContatoreRunnable(1,10);
ContatoreRunnable contatore2 = new ContatoreRunnable(20,30);
new Thread(contatore1).start();
new Thread(contatore2).start();
}
}
- 48 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
12. GESTIONE DEGLI ERRORI (EXCEPTION)
La soluzione tradizionale al malfunzionamento e' quella che il metodo restituisce un indicatore
sia nel caso di successo che in quello di insuccesso (i.e: readLine restituisce o una stringa o
null). Questo approccio ha due problemi:
• 1: il chiamante potrebbe dimenticare di controllare il valore restituito
• 2: il chiamante potrebbe non essere in grado di gestire un insuccesso: se non sa come
rimediare potrebbe lasciare al suo chiamante di gestirlo a sua volta: bella seccatura per il
programmatore che si trova a dover gestire potenziali mafunzionamenti annidati nei metodi
utilizzati.
Questa metodologia inoltre tende a far programmare "pensando all'insuccesso"
if (!x.faQualcosa()) return false;
anziche' pensando al successo:
x.faQualcosa();
In piu' il programma diventa di difficile lettura e quindi manutenzione.
Il meccanismo di gestione che usa le eccezioni risolve questi problemi:
• le eccezioni (almeno quelle controllate) non possono essere ignorate
• le eccezioni possono essere gestite da un gestore "competente" e non solo dal chiamante
del metodo fallito
12.1. Eccezioni controllate
Esempio: tutte quelle che derivano da IOException Sono quelle che dipendono da eventi
prevedibili, il cui accadere dipende, ad esempio, dall'uso che l'utente fa del programma (i.e
tenta di aprire un file che non esiste, o che non e' del formato corretto) Il compilatore deve
sapere cosa fare con queste eccezioni.
ATTENZIONE: esistono casi di eccezioni che dovrebbero essere controllate (cioe' dovrebbe
essere richiesto sempre un gestore) e che invece non lo sono: ad esempio Integer.parseInt
lancia NumberFormatException che e' non controllata. Cio' non vieta di installare un gestore...
12.2. Eccezioni non controllate
Esempio: quelle che estendono RuntimeException o Error Sono quelle dovute da un errato
uso dell'oggetto da parte del PROGRAMMATORE e quindi non prevedibili (i.e. tentare di
leggere da un file che non e' stato possibile neppure aprire: il puntatore e' null)
12.3. Gestione delle eccezioni
12.3.1. Sollevare una eccezione in caso di malfunzionamento
E' la parte piu' facile: basta chiamarla.
Esempio: si stanno leggendo dei record da file costituiti da tre linee ognuno. Se ad un certo
punto dopo la prima riga di un record il file finisce non siamo in una condizione corretta.
String in = readLine();
if (in == null) {
EOFException exc = new EOFException ("Fine file in lettura");
throw exc;
}
oppure
- 49 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
String in = readLine();
if (in == null)
throw new EOFException ("Fine file in lettura");
dopo aver sollevato l'eccezione il metodo finisce immediatamente, come se si fosse eseguito un
return
12.3.2. Intercettazione delle eccezioni
Se una eccezione non e' intercettata da un qualche gestore il programma si blocca. E'
neccessario quindi preparare un gestore per ogni tipo di eccezione che puo' accadere.
Un gestore delle eccezioni si installa con un blocco try contenente delle clausole catch.
Esempio
try {
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("Quanti anni hai?");
String inLine = in.readLine();
-- puo' sollevare IOException
int age = Integer.parseInt(inLine);
-- puo' sollevare NumberFormatException
age++;
System.out.println("L'anno prossimo avrai " + age + " anni.");
}
catch (IOException e) {
System.out.println("Errore input/output");
}
catch (NumberFormatException e) {
System.out.println("L'input non era un numero.");
}
finally {
-- da eseguire sia in caso di eccezione che normalmente
-- solitamente contiene ad esempio la chiamata alla close dei
-- file aperti
}
Esempi di gestione delle eccezioni
a) ORRENDO nasconde il problema: catch (myException e) {}
b) Stampa dello stack (meglio che niente)
catch (myException e) { e.printStackTrace(); }
c) messaggio di log
catch (myException e) {
System.out.println("input errato: " +e);
}
d) gestione di ritentativi in caso di errore
esempio (contalinee)
boolean done = false;
String filename = JOptionPane.showInputDialog("Nome del file:");
BufferedReader reader;
int counter = 0;
while (!done) {
try {
reader = new BufferedReader(new FileReader(filename));
// usa il file... ad esempio contandone le linee
while(!done) {
String input = reader.readLine();
if (input == null) done = true; // fine del
file
else counter++;
}
} catch (IOException e) {
System.out.println("Input/output error: "+e);
} catch (NumberFormatException e) {
e.printStackTrace();
}
if (!done) {
// concede un'altra possibilita'
filename=JOptionPane.showInputDialog("Prova un altro
file:");
if (filename==null) // se non inserisce nulla finisce
done=true;
- 50 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
}
}
12.3.3. Creazione di un nuovo tipo di eccezione
a) si sceglie da chi estendere a seconda che si richieda sia sempre
creato un gestore o no (vedi Gestioni controllate e non)
b) si crea una nuova classe contenente solo due costruttori:
public class myException extends RuntimeException {
public myException() {}
public myException(String ragione) { super(ragione); }
}
la "ragione" e' la stringa che viene mostrata nella JVM quando
accade l'eccezione e si stampa lo stack
12.3.4. Esempi di uso delle eccezioni: FifoQueue
src/FifoQueue.java
/** Gestione di una coda di numeri interi, con gestione delle eccezioni.
* @author Luigi Ferrari
* @version 1.1 del 31.1.2004
*/
/** Eccezioni della coda FIFO */
class CodaVuotaException extends RuntimeException {
public CodaVuotaException () {}
// Nessuna gestione implicita
}
class CodaPienaException extends RuntimeException {
// posso mettere piu' costruttori, anche con parametri
public CodaPienaException (String motivo) {
System.out.println("CodaPienaException: motivo: " + motivo);
}
}
class IndiceErratoException extends RuntimeException {
public IndiceErratoException (int x) {
System.out.println("IndiceErratoException: la posizione " + x + " non esiste");
}
}
/** Coda FIFO */
public class FifoQueue {
private int[] dati;
private int puntoInserimento;
private int puntoEstrazione;
private int datiPresenti;
/** Costruttori */
public FifoQueue(int dim) {
dati = new int[dim];
puntoInserimento = 0;
puntoEstrazione = 0;
datiPresenti = 0;
}
public FifoQueue()
this(100);
}
{
/** Inserisce un dato nella coda
* @param x
dato da inserire
* @return none, CodaPiena exception generate if queue is full
*/
public void insert(int x) throws CodaPienaException {
if (datiPresenti == dati.length)
throw new CodaPienaException("Inserzione di " + x);
dati[puntoInserimento] = x;
puntoInserimento++;
if (puntoInserimento == dati.length) puntoInserimento = 0;
datiPresenti++;
}
- 51 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
/** Estrae un dato dalla coda
* @return dato estratto
*/
public int get() throws CodaVuotaException {
int dato;
if (datiPresenti == 0) throw new CodaVuotaException();
dato = dati[puntoEstrazione];
puntoEstrazione++;
if (puntoEstrazione == dati.length) puntoEstrazione = 0;
datiPresenti--;
return dato;
}
/** Indica se la coda e' vuota.
* @return true se la coda e' vuota, false altrimenti
*/
public boolean isEmpty() {
if (datiPresenti == 0) return true;
return false;
}
/** Restituisce un dato della coda. Utile se volio fare una interfaccia grafica
* che visualizzi il contenuto della coda
* @param pos posizione nell'array (0..(N-1))
* @return il dato nella posizione indicata
*/
public int getDato(int pos) throws IndiceErratoException {
if (pos >= dati.length || pos < 0) throw new IndiceErratoException(pos);
return dati[pos];
}
/** Debug */
public void show(String s) {
System.out.println(s + ": pInserimento " + puntoInserimento +
" pEstrazione " + puntoEstrazione +
" datiPresenti " + datiPresenti);
for (int i=0; i<dati.length; i++)
System.out.println("Dati["+i+"]="+dati[i]);
}
}
Classe di test (src/FifoQueueTest.java)
/** Test della classe FifoQueue */
public class FifoQueueTest {
public static void main(String[] args) {
FifoQueue f = new FifoQueue(5);
try {
for(int i=1; i<5; i++) f.insert(i);
System.out.println ("estrae 1: " + f.get());
f.insert(5);
f.insert(6);
System.out.println ("Fallisce l'inserimento:");
f.insert(7); // commentare se si vuole provare l'altra eccezione
}
//try
catch (CodaVuotaException e) {
System.out.println("BLOCCO TRY..CATCH: Impossibile estrarre, coda vuota");
} // catch
catch (CodaPienaException e) {
System.out.println("BLOCCO TRY..CATCH: Impossibile inserire, coda piena");
} // catch
finally {
// eventuali istruzioni da eseguire comunque
System.out.println("BLOCCO FINALLY");
}
try {
System.out.print("Contenuto della coda:");
for (int i = 0 ; i<=5; i++)
System.out.print(" "+f.getDato(i));
}
//try
catch (IndiceErratoException e) {
System.out.println("BLOCCO TRY..CATCH: Passato indice errato a getDato");
} // catch
try {
while (!f.isEmpty())
// svuota la coda
System.out.println ("estrae: " + f.get());
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 52 -
LF Java Handbook
System.out.println("Fallisce l'estrazione perche' coda vuota:");
int x=f.get();
// fallisce, coda vuota!
System.out.println("Di qui non dovrebbe passare...");
}
//try
catch (CodaVuotaException e) {
System.out.println("BLOCCO TRY..CATCH: Impossibile estrarre, coda vuota");
} // catch
finally {
// eventuali istruzioni da eseguire comunque
System.out.println("BLOCCO FINALLY: FINE DEL PROGRAMMA");
}
}
}
- 53 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
13. DESIGN PATTERNS
13.1. Singleton
Riferimenti:
• Singleton: : Design Patterns, Mokabyte n.64 Maggio 2002 Giancarlo Crocetti.
• Objetc pooling: : Mokabyte n... Giovanni Tommasi.
• Metzker, pattern design, p.83: esempio che usa il monitor della classe per evitare problemi
con i threads.
Si usa per avere una singola istanza di una classe.
Caratteristica principale:
• un costruttore privato che garantisce la singola istanza
• un costruttore pubblico e statico getIstance()
Struttura base del Singleton
public class Singleton{
private static Singleton instance = null;
private Singleton () { ...}
public static Singleton getInstance() {
if (instance == null) instance = new Singleton();
return instance;
}
//altri metodi
}
Esempi di uso:
• connection pool
• generazione di SID globali
• DesktopView
13.1.1. Esempio di implementazione (versione mia, non e' quello classico)
Note:
• per rendere impossibile allocare risorse ad altri che il Gestore che usa il singleton ho
incapsulato la risorsa e il suo gestore di pool in un package separato e ho dichiarato il
costruttore della risorsa protected.
• per liberare una risorsa potrebbe bastare il free del riferimento senza passare per la ricerca
nell'array`
• nell'esempio il Singleton e' duplicato e i metodi sono tutti statici: <<< e' possibile migiorare
separando la richiesta di una istanza del pool dalla concessione dell'istanza della risorsa
Risorsa r = Pool.getInstance().getRisorsa();
src/GestoreRisorse/PackageRisorse/GestoreRisorse.java
package PackageRisorse;
import java.util.ArrayList;
import java.util.Iterator;
/** Gestisce un pool di risorse.
* Usa il pattern Singleton.
* Utilizza una classe interna RisorsaIncapsulata che contiene la risorsa
* e il suo stato
* @author L.Ferrari
* @version 1.0 del 31.1.2004
- 54 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
*/
public class GestoreRisorse
{
// instance variables - replace the example below with your own
static private GestoreRisorse instance = null;
private static ArrayList pool;
private static final int NUM = 3;
/** Costruttore */
private GestoreRisorse() {
pool = new ArrayList();
for (int i=0; i< NUM; i++) {
RisorsaIncapsulata r = new RisorsaIncapsulata("R"+(i+1));
pool.add(r);
}
}
/**
* Alloca una risorsa se disponibile.
* Usa il pattern Singleton per allocare se stesso la prima volta
* e rendersi univoco.
* @param owner stringa che identifica il proprietario della risorsa
* @return una risorsa, se disponibile, null altrimenti
*/
public static Risorsa getInstance(String owner) {
if (instance == null)
instance = new GestoreRisorse();
Iterator it = pool.iterator();
while (it.hasNext()) {
RisorsaIncapsulata ri= (RisorsaIncapsulata)it.next();
if (ri.isAssigned() == false) {
ri.assign(owner);
return ri.getRisorsa();
}
}
return null; // non c'erano risorse disponibili
// in alternativa qui potrei aggiungere una nuova risorsa all'array
// e restituire quella.
}
/** Rilascia una risorsa.
* Usa il pattern Singleton.
* @param r risorsa da rilasciare
*/
public static void releaseInstance(Risorsa r) {
if (instance == null) instance = new GestoreRisorse();
Iterator it = pool.iterator();
while (it.hasNext()) {
RisorsaIncapsulata ri = (RisorsaIncapsulata)it.next();
if (r == ri.getRisorsa()) {
ri.free();
return; // ho finito; se fossero troppe potrei diminuirle...
}
}
}
/** Stampa lo stato del GestoreRisorse */
public static void print() {
System.out.print("\nStato del Gestore delle Risorse: ");
System.out.println("sono gestite "+pool.size()+" risorse");
Iterator it = pool.iterator();
while (it.hasNext()) {
RisorsaIncapsulata ri = (RisorsaIncapsulata)it.next();
System.out.println(ri.status());
}
System.out.println("");
}
/** Classe che ingloba la risorsa di cui si vogliono gestire n istanze */
private class RisorsaIncapsulata {
private Risorsa risorsa;
// la risorsa da gestire
private boolean assigned;
// true se la risorsa e' data a qualcuno
private String owner;
// possessore della risorsa
public RisorsaIncapsulata(String name){
risorsa = new Risorsa(name);
assigned = false;
owner = null;
}
/** Assegna la risorsa, se libera, a qualcuno
* @param owner chi richiede la risorsa
* @return true se la risorsa e' stata assegnata, false se gia' in uso
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 55 -
LF Java Handbook
*/
public boolean assign(String owner){
if (assigned == true) return false;
this.owner = owner;
assigned = true;
return true;
}
/** Libera la risorsa */
public void free(){ assigned = false; }
/** Indica se la risorsa e' gia' assegnata a qualcuno
* @return true se la risorsa e' assegnata
*/
public boolean isAssigned(){ return assigned; }
/** Stato della risorsa
* @return stato della risorsa in formato stringa comprensibile
*/
public String status(){
return ("Risorsa " + risorsa.getName() +
(assigned?" assegnata a "+owner+".":" disponibile."));
}
/** Risorsa vera e propria
* @return la risorsa
*/
public Risorsa getRisorsa() { return risorsa; }
}
}
src/GestoreRisorse/PackageRisorse/Risorsa.java
package PackageRisorse;
/**
* Generica risorsa di cui si vogliono gestire n istanze
* Potrebbe essere una connessione ad un database, una connessione a delle
* linee di trasmissione, un'area di memoria etc.
* @author L. Ferrari
* @version 1.0 del 31.1.2004
*/
public class Risorsa
{
private String name;
// nome della risorsa
/**
* Costruttore: e' protected in modo che solo le classi del package
* (e in particolare il pool manager) possano accedervi.
*/
protected Risorsa(String name){ this.name = name; }
// possono essere definiti quanti metodi si vogliono
/** Nome della risorsa
* @return nome
*/
public String getName(){ return name; }
}
13.2. SenderArgument
Scopo: fare in modo che un oggetto su cui e' chiamato un metodo possa agire sull'oggetto
chiamante.
Riferimenti: http://patterndigest.com/patterns/SenderArgument.html .
Soluzione: si passa un riferimento all'oggetto corrente utilizzando la parola chiave this:
unOggetto.faQualcosa(this);
Note: utilizzato quando e' necessario che il ricevitore conosca chi e' il mittente, utilizzato nel
pattern Observer e nel pattern Relationship Object.
13.3. Iteratore
- 56 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Scopo: consentire un metodo di esplorazione di collezioni
implementazione reale.
Si dichiara come classe interna di una classe.
Esempi di uso:
• vedi il capitolo di "StringTokenizer" nel capitolo relativo alle stringhe.
indipendente
dalla
• vedi il capitolo di "Strutture dati astratte".
• vedi il capitolo di "Collezione di oggetti".
13.4. Observer
E' un pattern comportamentale.
Scopo: disaccoppiare il piu' possibile le diverse parti di una applicazione adibite al controllo,
all'accesso ai dati e alla presentazione.
Spesso il controller e' un listener.
Riferimenti: Mokabyte n.70, Gennaio 2003 (troppo complesso in alcune parti).
13.4.1. Realizzazione tramite Observer-Observable
Sono classi di java.util.
Questo modello a' meno utilizzato del successivo che usa i JavaBeans, perche' una delle
classi deve estendere Observable e ci possono essere problemi se si deve ereditare gia' da
un'altra classe.
Esempio di uso: sudoku. Il pattern e' utilizzato nella mia realizzazione di sudoku per
consentire alle classi piu' interne di propagare il loro cambiamento di stato a quelle che le
usano, qualora l'oggetto della classe piu' interna (una cella) sia condiviso da piu' oggetti della
classe piu' esterna (insiemi di nove celle che le condividono).
Esempio di pattern Observer realizzato tramite classi observer-observable.
13.4.2. Realizzazione tramite JavaBean
E' un modello a componenti. Uno dei principali obiettivi e' quello di realizzare un basso
accoppiamento tra soggetto osservato e osservatori.
Il soggetto osservato non sa nulla dell'osservatore o degli osservatori (che vengono chiamati
listener in questo modello).
E' possibile utilizzare delle classi anonime per implementare l'interfaccia ActionListener nel
- 57 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
soggetto da osservare.
Esempio tratto da Object Oriented Design and Patterns, p.160.
unBottone.addActionListener( new
ActionListener() {
public void actionPerformed(ActionEvent evento) {
// qui ci va quello che deve essere fatto quando il bottone viene premuto
unTextField.setText("Bottone premuto");
}
});
Esempio tratto da Object Oriented Design and Patterns, cap. 4. (src/TimerTester.java)
package ch4.timer;
import
import
import
import
import
java.awt.*;
java.awt.event.*;
java.util.*;
javax.swing.*;
javax.swing.Timer;
/**
This program shows a clock that is updated once per second.
*/
public class TimerTester
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
final int FIELD_WIDTH = 20;
final JTextField textField = new JTextField(FIELD_WIDTH);
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(textField);
ActionListener listener = new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
Date now = new Date();
textField.setText(now.toString());
}
};
final int DELAY = 1000;
// Milliseconds between timer ticks
Timer t = new Timer(DELAY, listener);
t.start();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
TimerTester in azione.
TO DO: Non e' ancora chiaro come sia possibile utilizzare il metodo dei JavaBean con classi
qualunque come soggetti da osservare. Probabilmente e' sufficiente che implementino qualche
interfaccia...
13.4.3. Applicazione di Observer: pattern MVC (Model View Controller)
Si dividono le responsabilita' in tre:
• Model: si occupa della rappresentazione dei dati della applicazione; deve modificare lo
- 58 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
stato a seguito di richieste effettuate dall'utente tramite il controller; deve notificare i
cambiamenti del proprio stato alla o alle viste del modello (pattern Observer).
Non conosce nulla dei suoi controller e delle sue view.
• View: e' la vista (interfaccia utente) del modello: per ogni modello possono esserci piu'
viste; invia al controller eventuali richieste dell'utente.
Interagisce con il model tramite un riferimento ad esso.
• Controller (o listener): interpreta le richieste della view (input dell'utente) e le trasforma in
azioni che vanno a modificare il model o che cambiano la view.
Interagisce con il model tramite un riferimento ad esso.
Vantaggi:
• c'e' una netta separazione tra i componenti del programma che possono essere sviluppati
in meniera indipendente
• il collegamento tra modello e view e tra modello e listener avviene a runtime.
Esempio di pattern MVC: bottone che cambia colore mentre e' tenuto premuto:
• Model: = attributo che contiene il codice del colore.
• View: = colorazione del bottone sul video.
• Controller: = modulo di gestione dell'evento pressione.
13.4.4. Java Message Service (JMS)
E' un altro esempio di implementazione del pattern Observer; consente a un numero
indefinito di sottoscrittori di essere avvisati a seconda del tipo di messaggio che e' stato
generato e per cui si sono registrati.
13.4.5. Problemi del pattern Observer
• L'oggetto osservato non sa nulla degli Osservatori (listener) per cui per il garbage collector
non e' possibile rimuoverli prima che sia stato rimosso l'oggetto osservato.
• Non e' garantito l'ordine con cui vengono "svegliati" i listener. Se si vuole una notifica a
"cascata" interporre classi in mezzo che realizzino l'ordine.
13.5. Command
Ne esistono almeno due versioni.
13.5.1. Insieme di comandi che producono output diversi (es. gitelf)
Consente di produrre piu' output da uno stesso input. E' possibile aggiungere nuovi formati di
uscita senza modificare la classe che esegue il parsing dell'input.
Le classi sono:
• Interfaccia <output>Builder: prevede una serie di metodi, uno per ogni possibile comando
trovato nell'input.
• Una o piu' classi che implementano l'interfaccia <output>Builder in concreto
• Director: il costruttore ha in input un ouputBuilder; esegue il parsing dell'input e per ogni
comando trovato chiama il metodo sull'oggetto OutputBuilder.
• Lancio: e' la classe che crea piu' oggetti Director, uno per ogni output, passando a ciascuno
il giusto oggetto che implementa <output>Builder.
Come si procede:
• si individuano i comandi da processare;
- 59 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
• si scrive l'interfaccia <Output>Builder;
• si realizza il parser che individua i comandi e li applica a oggetti di tipo <output>Builder;
• si realizzano le classi che producono l'output;
• si scrive la classe Lancio. Se servono piu' output si crea un nuovo oggetto di tipo
<output>Builder e un nuovo director.
Svantaggi: Il parsing viene effettuato una volta per ogni output.
Verificare la possibilita' di utilizzare insieme il pattern observer per evitare questo problema.
13.5.2. Comando che deve essere lanciato da piu' fonti: Action
Riferimenti: ad es. Horstmann, ObjectOriented Design and Patterns, p.399.
Il pattern command e' utilizzato in Swing per consentire di eseguire un comando da diverse
fonti di input, ma puo' essere utilizzato in altri casi.
Il comando puo' avere anche uno stato oltre che dei comportamenti.
Si utilizza l'interfaccia Action che corrisponde ad un comando. E' possibile poi utilizzare il
metodo actionPerformed() per lanciarlo.
Stato: come esempi di stato ci possono essere il fatto di essere abilitato o meno, il nome, una
icona, etc. L'abilitazione o la disabilitazione viene fatta in Swing con setEnabled() mentre le altre
proprieta' possono essere settate utilizzando le costanti del tipo Action.
Esempio di applicazione del pattern Command con Action (src/GUISeparataTest.java)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
- 60 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
/**
* <p>Title: GUISeparataTest </p>
* <p>Description: Interfaccia grafica separata dalla gestione degli eventi.</p>
* <p>Copyright: Copyright (c) Luigi Ferrari, 2002</p>
* <p>Company: Luigi Ferrari</p>
* @author Luigi Ferrari, [email protected]
* @version 1.0
*/
/** Azioni logiche: colorare lo sfondo della form
*/
class ColorAction extends AbstractAction {
private Component target;
public ColorAction(String name, Icon icon, Color c, Component comp) {
putValue(Action.NAME,name);
putValue(Action.SMALL_ICON, icon);
putValue("Color", c);
target = comp;
}
public void actionPerformed(ActionEvent evt) {
Color c = (Color)getValue("Color");
target.setBackground(c);
target.repaint();
}
}
/** definizione di bottoni in base a delle azioni logiche
* ne basta una perche' le azioni sono le stesse
*/
class ActionButton extends JButton {
public ActionButton(Action a) {
setText((String)a.getValue(Action.NAME));
Icon icon = (Icon)a.getValue(Action.SMALL_ICON);
if (icon != null) setIcon(icon);
addActionListener(a);
}
}
/* Interfaccia utente */
class GUISeparata extends JFrame {
public GUISeparata() {
/* aspetto generale della form */
setTitle("Esempio di Interfaccia Utente separata dalle azioni");
setSize(300,200);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0);}
});
JPanel panel = new JPanel();
/* definizione delle azioni logiche */
ColorAction blueAction = new ColorAction ("Blue",
new ImageIcon("blue_ball.gif"),
Color.blue, panel);
ColorAction yellowAction = new ColorAction ("Yellow",
new ImageIcon("yellow_ball.gif"),
Color.yellow, panel);
ColorAction redAction = new ColorAction ("Red",
new ImageIcon("red_ball.gif"),
Color.red, panel);
/* associazione dei pulsanti alle azioni logiche */
panel.add(new ActionButton(yellowAction));
panel.add(new ActionButton(redAction));
panel.add(new ActionButton(blueAction));
/* associazione dei tasti della tastiera alle azioni logiche */
panel.registerKeyboardAction(yellowAction,
KeyStroke.getKeyStroke(KeyEvent.VK_Y,0),
JComponent.WHEN_IN_FOCUSED_WINDOW);
panel.registerKeyboardAction(redAction,
KeyStroke.getKeyStroke(KeyEvent.VK_R,0),
JComponent.WHEN_IN_FOCUSED_WINDOW);
panel.registerKeyboardAction(blueAction,
KeyStroke.getKeyStroke(KeyEvent.VK_B,0),
JComponent.WHEN_IN_FOCUSED_WINDOW);
/* inizializzazione sfondo */
Container contentPane = getContentPane();
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 61 -
LF Java Handbook
panel.setBackground(Color.white);
contentPane.add(panel);
/* associazione di voci di menu' alle azioni logiche */
JMenu m = new JMenu("Color");
m.add(yellowAction);
m.add(blueAction);
m.add(redAction);
JMenuBar mbar = new JMenuBar();
mbar.add(m);
setJMenuBar(mbar);
}
}
public class GUISeparataTest {
public static void main(String[] args) {
JFrame f = new GUISeparata();
f.pack();
// ATTENZIONE: serve se non ho specificato le
// dimensioni di base per adattare la finestra ai
// componenti che ci sono dentro.
f.show();
}
}
13.6. Proxy
Vedi anche Argomenti avanzati - riflessione.
13.7. Facade
Lo scopo e' nascondere la realizzazione di un comportamento utilizzando un classe che
espone l'interfaccia. Sotto la classe puo' esserci addirittura piu' di una classe, ad esempio per
rendere persistenti degli oggetti.
Puo' essere utilizzato per disaccoppiare parti di sistema fornendo una interfaccia di alto livello
che utilizza i metodi delle classi nascoste per realizzare il comportamento voluto.
E' utilizzato ad esempio nei javabean (v).
- 62 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
14. Esempi di Object Oriented Design
14.1. Forza 4
Il gioco Forza 4 con architettura client-server.
Non e' stato ancora implementato.
L'immagine e' stata realizzata con Violet di Horstmann.
- 63 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
15. APPLICAZIONI ENTERPRISE
15.1. Servlet
Sono eseguite sul server remoto.
In pratica una servlet e' una API utilizzata dal Web Server per fornire nuovi servizi. Di solito
non hanno alcuna interfaccia grafica.
Vengono attivate una volta solo alla attivazione del Server, possono ricordare lo stato. Inoltre
possono comunicare tra loro anche attraverso pipeline.
Per programmare utilizzando le servlet non basta il normale java sdk, serve la versione
enterprise.
ATTENZIONE: sembra invece che basti il normale sdk integrato con il file servlet.jar, che
deve essere messo nella dir jre\lib\ext del jdk oppure aggiunto a CLASSPATH.
15.1.1. Esempio di servlet
Attenzione: codice non provato ma compilato (sapilf/java/testservlet).
File ProvaServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ProvaServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
PrintWriter out = res.getWriter();
out.println("Servlet di prova");
}
}
Dopo la compilazione con j2ee deve essere messo sotto httpd/servlet.
Per lanciarlo sul browser selezionare http://host/servlet/ProvaServlet
15.2. JavaBean
Riferimento: Horstmann, Object Oriented design and patterns.
Un javabean e' un sistema di una o piu' classi che realizza uno scopo.
Spesso e' utilizzato nelle applicazioni enterprise per incapsulare i dati che sono resi
persistenti in modo trasparente.
E' contraddistinto da:
• attributi come le classi normali.
• metodi getter e setter: possono non esserci tutti, possono fare delle operazioni complesse,
come ad esempio occuparsi della persistenza, ad esempio prendendo e scrivendo i dati in
un database.
• puo' generare eventi.
La sua interfaccia e' di solito realizzata con una singola classe facade (secondo il pattern
facade) che nasconde la struttura interna, composta anche da piu' classi.
15.2.1. Creazione di un file jar con il javabean
Occorre creare un manifesto che esponga la classe facade. Vedi libro.
15.2.2. Loading di un javabean in un IDE
Vedi libro.
- 64 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
16. JDBC - JAVA E I DATABASE
16.1. Connessione e disconnesione dal database
Nell'esempio si fa riferimento a database Oracle.
/* Costanti */
private static final String dbUser
private static final String dbPassword
/* Variabili */
private static Connection
private static boolean
public static String
public static String
= "user";
= "password";
dbConnection;
dbIsConnected = false;
dbSid
= "theSID";
dbServerAddr = "hostname"; // "192.168.123.18";
/* it make takes time... */
public static final Connection dbGetConnection()
throws SQLException, java.lang.InterruptedException
{
if (dbIsConnected) return dbConnection;
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
dbConnection = DriverManager.getConnection(
"jdbc:oracle:thin:@" + dbServerAddr + ":1521:" + dbSid,
dbUser,dbPassword);
dbIsConnected = true;
System.out.println ("dbGetConnection: connected.");
return dbConnection;
}
public static final void dbCloseConnection ()
{
try {
if (dbIsConnected) {
dbConnection.close();
System.out.println ("dbCloseConnection: disconnected.");
dbIsConnected = false;
}
} catch ( SQLException e ) {
System.out.println ("dbCloseConnection: " + e);
}
}
Sono utili anche delle funzioni locali che aprono e chiudono la connessione e creano uno
statement in un unico colpo:
private Statement createStatement() {
Statement stmt=null;
Connection conn;
try {
// Open connection & statement
conn = dbGetConnection();
return conn.createStatement();
} catch ( Exception e ) {
e.printStackTrace(e);
return null;
}
}
private void destroyStatement(Statement stmt) {
try {
//Close connection & statement
stmt.close();
dbCloseConnection();
} catch ( Exception e) {
e.printStackTrace(e);
}
}
16.2. Select
- 65 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Select con cursore
String query =
"select cod, dsc "
+ " from database.tabella "
+ " where cod < " + valminimo
+ " database.tabella order by cod";
Statement stmt = createStatement();
try {
ResultSet rs = stmt.executeQuery(query);
while (rs.next()){
System.out.println("Read: cod="+ rs.getString(1)
+ " description: " + rs.getString(2));
}
} catch (Exception e) {
System.out.println("ERROR: query is: "+query);
// Proseguo con la chiusura del db senza lancio di eventuali exception
Sapi.dbCloseConnection();
return;
}
destroyStatement(stmt);
16.3. Chiamata di stored procedure
private long chiamataDiStroredProcedure(long par1, long par2) {
int reply=0;
Connection conn;
try {
conn = dbGetConnection();
} catch ( Exception e ) {
e.printStackTrace();
return 0;
}
try {
CallableStatement stm =
conn.prepareCall("{? = call db.xxx(?,?,?,?)}");
stm.registerOutParameter(1, java.sql.Types.TINYINT); //reply
stm.setLong(2, par1);
// parametro 1 (input)
stm.setLong(3, par2);
// parametro 2 (input)
stm.registerOutParameter(4, java.sql.Types.INTEGER); // out 1
stm.registerOutParameter(5, java.sql.Types.INTEGER); // out 2
ResultSet rs = stm.executeQuery();
rs.next();
reply = stm.getInt(1);
if (reply != 0) {
jStatusBar.setText("ERROR: Stored procedure xxx failed. "R);
return -1;
}
return stm.getInt(4);
} catch (SQLException e) {
e.printStackTrace(e);
return -1;
}
}
16.4. Insert e delete
Da fare
16.5. Istruzioni DDL
Da fare
- 66 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
17. DATABASE SERVER HSQLDB
Scaricato da internet, www.hsqldb.org, versione installata: 1.7.1.
E' gratuito.
I dati sono salvati in chiaro come comandi sql.
Sono disponibili diverse versioni del database:
• in memoria
• stand alone (un singolo programma che lo usa)
• server: piu' programmi possono accedere insieme al database.
• webserver: non ancora provata.
17.1. Installazione
Si scompatta il file dato in una dir qualunque, quello che importa e' che la libreria sia
accessibile.
E' possibile ricostruire la libreria per la versione jdk che si usa.
17.2. Utility
17.2.1. DatabaseManager
consente di operare sul database tramite SQL:
@java -cp [DIR_DELLA_LIB]\hsqldb.jar org.hsqldb.Server -database nomedb
17.2.2. ScriptTool
lancia uno script sul database:
@java -cp [DIR_DELLA_LIB]\hsqldb.jar org.hsqldb.util.ScriptTool
-database nomedb -script nomescript -log true >> file_di_log
17.3. Versione server
Operazioni da effettuare:
-
creare il database con ScriptTool
creare un file che lanci il server
provare ad accedere al database tramite DatabaseManager
scrivere un programma java che accede al database.
17.4. Organizzazione delle dir
Rispetto alla dir del progetto:
bin
contiene gli script per la gestione
builddb.bat
runserver.bat
runmanager.bat
Eventualmente creare dei collegamenti per poterli lanciare da Windows.
data contiene il database:
nomedatabase.properties
nomedatabase.script
ddl
contiene gli script per la creazione del database da zero
NB: uso LF_HOME come dir di partenza, nella sottodir lib ho messo hsqldb.jar
- 67 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
17.4.1. Esempio di script per la creazione di un database
/bin/builddb.bat
echo off;
echo
echo Creazione database...
set LF_HOME=e:/dellusers/luigi
Copyright Luigi Ferrari, 2003
cd ..\data
@java -classpath %LF_HOME%\lib\hsqldb.jar org.hsqldb.util.ScriptTool
-database nomedb -script ..\ddl\tableddl.sql -log true >..\log\b.log
echo Caricamento Look-up tables...
@java -cp %LF_HOME%\lib\hsqldb.jar org.hsqldb.util.ScriptTool -database nomedb
-script ..\ddl\lutdata.sql -log true >>..\log\b.log
echo Caricamento dati di test...
@java -classpath %LF_HOME%\lib\hsqldb.jar org.hsqldb.util.ScriptTool
-database nomedb -script ..\ddl\testdata.sql -log true >>..\log\b.log
echo Database creato.
cd ..\bin
dove ad esempio il file ddl/tableddl.sql e' fatto da statement Sql; per i commenti si usa una
doppia lineetta iniziale:
File: ddl/tabledd.sql
-- File name: nomedb.sql
-- Author: Luigi Ferrari
-- Copyright: Luigi Ferrari - [email protected]
-- Version: 1.0 del 21.3.3
-- tables drop
drop table Table1 if exists;
go
-- Tables
CREATE TABLE Table1 (
codice CHAR NOT NULL primary key,
descrizione VARCHAR(30)
);
go
17.4.2. Esempio di avvio del server
ATTENZIONE: nella dir di lancio deve essere presente il file server.properties che contiene la
posizione del database rispetto alla directory di lancio.
Ad esempio, se lo lancio dalla dir bin e il database e' nella dir data:
File server.properties
server.database=../data/nomedatabase
Se il nome del database contiene il nome del nodo ed e' in una cartella condivisa dovrebbe
essere accessibile anche dalla rete (da verificare).
File: bin/runserver.bat
set echo off
echo
Copyright Luigi Ferrari, 2003
echo Lancia il server del database...
echo Il nome del database e' preso dal file server.properties
@java -cp %LF_HOME%/lib/hsqldb.jar org.hsqldb.Server
17.4.3. Esempio di avvio del manager del database in versione standalone e server
- 68 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
NOTA: Se e' lanciato per la versione server il server deve essere gia' stato attivato
(runserver) e non serve il nome del database (basta l'indicazione //localhost)
File: bin/runmanager.bat
echo off;
echo
echo Manager del database...
Copyright Luigi Ferrari, 2003
rem versione stand alone:
rem @java -cp %LF_HOME%\lib\hsqldb.jar org.hsqldb.util.DatabaseManager
-url jdbc:hsqldb://W11/w11-d/users/luigi/projects/GiteLF/data/gite
rem versione con server
@java -cp %LF_HOME%\lib\hsqldb.jar org.hsqldb.util.DatabaseManager
-url jdbc:hsqldb:hsql://localhost
17.4.4. Esempio per vedere il contenuto del database
ATTENZIONE: e' da mettere a posto, mi sembra che non funzioni.
echo off;
echo
Copyright Luigi Ferrari, 2003
echo Show data...
set LIB=%LF_HOME%\lib
cd ..\data
@java -cp %LF_HOME%\lib\hsqldb.jar org.hsqldb.util.ScriptTool -database nomedb
-script ..\ddl\show.sql -log true >..\log\s.log
echo ...
echo Data wrote into ../log/s.log
echo File view:
edit ..\log\s.log
exit
- 69 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
18. TIPS: Soluzione di problemi
18.1. Standard main - DA RISOLVERE
Deve avere le seguenti funzionalita'
• gestione argc argv (o parametri della applet in alternativa)
• gestione opzioni
• usage
• copyright
• log
• equivalente del c per uscire in caso di errore
Vedere il capitolo main sotto programmazione.gpp per la conversione dei parametri in liste.
18.2. log - DA FARE
Vedere GiteXML, dovrebbe gia' essere fatto.
NB da Java 1.4 esistono le API apposite. Mettere qui esempio pratico.
18.3. Out Of Memory
Se un programma va in out of memory e' possibile incrementare la dimensione massima
dell'heap rispetto alla simensione standard di 64 MB, portandola ad esempio a 256MB:
java -Xmx256m -cp ... ClasseMain.class
java -Xmx256m -jar /home/cay/web/com/violet/violet.jar
(Kay Hortsmann, manuale d'uso del programma Violet per il disegno di diagrammi UML).
18.4. Attributi che devono contenere valuta
Non e' mai una buona scelta utilizzare i valori double: conviene invece usilizzare gli interi o i
BigInteger prendendo come unita' di misura la piu' piccola frazione della valuta in questione e
facendo la conversione al momento della acquisizione e della stampa (da Kay Horstmann,
Object Oriented Design and Patterns", Wiley internation Edition).
18.5. Variabili che cambiano valore tra una chiamata e l'altra
Se un record di una variabile Vector non mantiene il proprio valore ma lo cambia ad ogni
aggiunta di un nuovo record significa che e' stata definita static (cioe' e' una variabile di classe e
non di istanza)
18.6. Check su variabile booleana restituita come oggetto
if (((Boolean)config.get("DEBUG")).booleanValue())
18.7. NullPointerException
potrebbe essere una variabile della classe che non e' stata inizializzata nel costruttore (ad
esempio e' stata creata nel main come variabile separata)
18.8. Stampa con Java - DA RISOLVERE
Esiste articolo da provare.
Esiste un progetto su sorgeforce.net GFP che lo risolve. Scaricato e messo provvisoriamente
- 70 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
su Dell85000//D:/tmp
18.9. Pulizia della memoria (garbace collection forzata)
Si ottiene con la chiamata: System.gc();
18.10. Calcolo del tempo di elaborazione
prima:
System.gc();
long startTime=System.currentTimeMillis();
dopo:
System.out.println("Completed in: " +
(System.currentTimeMillis()-startTime));
18.11. Controllo delle versione della JRE in esecuzione
String vers = System.getProperty("java.version");
if (!vers.equals("1.4.0_01")) {
// da migliorare...
...
}
18.12. Appleviewer non visualizza applet per problemi con X
Appletviewer fallisce dicendo:
impossibile al server invalid DISPLAY localhost:0.0
Soluzione: da una finestra come user root dare
xhost +
18.13. Netscape su Linux: visualizzazione di applet
Netscape all'apertura di una applet dice "JavaFormatError Bad Major Version Number"
Soluzione: ? Potrebbe essere un problema di difficile soluzione perche JRE 2 plug-in, secondo
la doc su W13, non va con Nescape 4.
18.14. Errori di arrotondamento
Non esiste 4.35, viene memorizzato come 4.349999999...
double f =4.35;
int n = (int)(100 * f);
System.out.println(n);
// stampa 434!!!
Usare invece:
int n = i(int)Math.round(100*f);
// 435
18.15. Conversione decimale-binario
In Java esiste il metodo statico toString
Integer.toString(n, 2)
Integer.parseInt(digitString, 2);
10 -> 2
2 -> 10
- 71 -
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
La base deve essere compresa tra 0 e 36.
18.16. Permissions sulle applet
Si verifica con Applet shipgate.
• si riesce a far girare con la connessione remota (cioe' con classe su PC con Windows che
si collega a DB oracle su Linux) solo da Jbuilder:
e' un problema di permissions:
Provato
senza
successo
a
copiare
il
file
c:\programmi\JBuilder7\jdk1.3\jre\lib\security\java.policy che ha le permission a ALL, sotto
c:\programmi\java\j2re1.4.0_01\bin Ho anche avviato il tool javapolicy (sempre sotto bin), e
riavviato il PC
• si riesce a far partire da Windows 98 con tutto sul server dopo aver trasferito anche tutte le
librerie necessarie (alcune delle quali sono di Oracle e alcune di Jbuilder).
• Client nome SAPI, Host SAPI
18.17. Random - Generazione di comportamenti casuali
Random randomGenerator;
randomGenerator = new Random();
int index = randomGenerator.nextInt();
int indexMinoreDi = randomGenerator.nextInt(max);
(0 : max-1)
int indexLimitato = randomGenerator.nextInt(min, max+1); (min : max)
long unLong = randomgenerator.nextLong();
18.18. Date and Time - Visualizzazione data corrente
public class MyClass {
SimpleTimeZone gdt;
SimpleDateFormat sdf;
Date currentTime;
public MyClass() {
gdt = new SimpleTimeZone(0, "GMT"); // forse inutile
sdf = new SimpleDateFormat("hh:mm:ss");
currentTime = new Date();
}
public String update() {
currentTime.setTime(System.currentTimeMillis());
return sdf.format(currentTime);
}
}
18.19. Date and Time - Classi standard
Dalla versione 1.1 a java.util.Date sono state aggiunte java.util.Calendar (la sua sottoclasse
da utilizzare e' java.util.GregorianCalendar) e java.util.DateFormat.
GregorianCalendar ha anche alcuni metodi utili tra cui before(GregorianCalendar) e
after(GregorianCalendar), booleani, che consentono il confronto tra due date.
// ECT: European Central Time
GregorianCalendar d = new GregorianCalendar(TimeZone.getTimeZone("ECT"));
d.setTime(new Date());
// d contiene la data corrente
// mette l'ora a mezzanotte:
d.set(Calendar.HOUR_OF_DAY, 24);
d.set(Calendar.MINUTE, 0);
d.set(Calendar.SECOND, 0);
d.set(Calendar.MILLISECOND, 0);
int day = d.get(Calendar.DAY_OF_MONTH);
int month = d.get(Calendar.MONTH) + 1;
- 72 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
ATTENZIONE: per estrarre il mese corrente fare attenzione al +1 (si parte da 0).
18.20. Problemi con piu' finestre
Ricordarsi di mettere System.exit(0) quando si usano finestre pop-up eccetera perche' sono
lanciate come thread separati e potrebbero sopravvivere al processo padre.
Cosa Succede nel caso delle applet?
18.21. Configurazione di una applicazione.
Utilizzare il package java.util.prefs.Preferences. Consente di memorizzare due livelli di
parametri di configurazione, uno di sistema e uno per ogni utente. La memorizzazione avviene
in modo dipendente dal sistema operativo ma trasparente per il programmatore. Le preferenze
fanno riferimento alla classe (o package) passato.
Per l'uso vedere Core Java Technologies Tech Tips del 15 Luglio 2003 e la documentazione
della classe java.util.prefs.Preferences.
ALTERNATIVA:
Esiste una mia api ConfigFile (vedi api.gpp) che consente di gestire i file di configurazione
della forma Nome=Valore.
Il problema e' comunque quello di far conoscere il nome del file a tutte le classi.
Soluzione adottata nel progetto jpp:
• Creata una classe con le costanti della applicazione, fra cui il nome della stessa, la
versione e il nome del o dei file di configurazione. Essa contiene anche un oggetto di tipo
ConfigFile statico (unico cosi' per tutta la applicazione); meglio sarebbe stato implementare
il singleton in ConfigFile.
• Una delle classi della applicazione conosce la posizione assoluta del file (ma a quel punto
potrebbe anche conoscerne il nome) e carica nell'oggetto ConfigFile la configurazione
corrente.
• Nelle classi che devono utilizzare i parametri di configurazione si prendeno con la chiamata
<classeCostanti>.<oggettoConfigFile>.getValue(key)
VEDERE ANCHE:
• progetto ccsapicc per la configurazione dei singoli processi
18.22. Associazione di un programma java al tipo di un file sotto Windows
Scopo e' quello di poter chiamare un programma java direttamente dal tasto destro del
mouse sul file.
Soluzione adottata in jpp:
• si crea una classe che accetta il nome di un file come argomento (i.e. JppStandAlone)
• si crea un file .bat che lancia il programma (vedi listing)
• si installa il file in un dir opportuna di installazione facendo in modo che tutti i riferimenti a
file di configurazione o altri input siano definiti con percorso assoluto.
• con tasto destro del mouse di sceglie Apri con.. e sfogliando si cerca il file bat.
Esempio di file batch (jppexe.bat) NB: La riga di lancio del file java e' tutta su una riga.
echo off
set LF_HOME=c:\Programmi\LF\jpp
@java -cp "%LF_HOME%/avalon-framework-cvs-20020806.jar;%LF_HOME%/xml-apis.jar;
%LF_HOME%/batik.jar;%LF_HOME%/xalan-2.4.1.jar;%LF_HOME%/xercesImpl-2.2.1.jar;
%LF_HOME%/fop.jar;%LF_HOME%/lfapi.jar;%LF_HOME%/jpp.jar" JppStandAlone %1
if ERRORLEVEL
goto err
0 goto ok
- 73 -
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
:err
echo "jpp: ...errore durante l'esecuzione"
goto done
:ok
echo "jpp: %1: xml and pdf created."
:done
pause
18.23. Creazione di un link per un programma java
Esempio di file batch (lancio di jpp a finestra) Attenzione ai file di configurazione che devono
essere installati nelle dir corrette.
ECHO Jpp: gpp (xml) to pdf converter
@java -cp "avalon-framework-cvs-20020806.jar;xml-apis.jar;batik.jar;xalan-2.4.1.jar;
xercesImpl-2.2.1.jar;fop.jar;lfapi.jar;jpp.jar" Jpp
Si crea poi un collegamento a questo file, nelle proprieta' si associa un'icona.
18.24. Organizzazione di una applicazione in librerie
Esempio: bluej bluej.jar:
• bluej\Boot.java
• bluej\Splash.java
• bluej\Splash.jpg
bluejcore.jar:
• bluej/
• bluej/classmgr/
• bluej/compiler/
• bluej/graph/
• ...
• bluej/utility/
• bluej/utility/filefilter/
• bluej/views/
• bluej/BlueJEvent.class
• bluej/BlueJEventListener.class
• bluej/BlueJTheme.class
• ...
• bluej/utility/Queue.class
• bluej/utility/SortedProperties.class
• bluej/utility/Utility.class$list() bluej/utility/
• ...
- 74 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
19. ALGORITMI
19.1. Strutture dati astratte
src/ListaCollegata.java
package StruttureDatiAstratte;
import java.util.NoSuchElementException;
/**
* ListaCollegata e' una versione semplificata della classe
* java.util.LinkedList che implementa una lista linkata doppia con
* i seguenti metodi (non sono gli unici):
* void addFirst(Object obj)
* void addLast(Object obj)
* Object getFirst()
* Object getLast()
* Object removeLast()
* Object removeFirst()
* Inoltre dispone di un iteratore listIterator che consente di esplorare
* la lista a piacimento tramite i metodi
* Object next() sposta l'iteratore in avanti (attenzione, solleva eccezione
*
NoSuchElementException se e' alla fine della lista) restituendo
*
l'oggetto estratto
* boolean hasNext()
* Object Previous()
* boolean hasPrevious()
* void add(Object)
aggiunge un oggetto nella posizione corrente
* void remove()
elimina l'oggetto nella posizione corrente
* Esempio di uso della classe LinkedList:
*
LinkedList list = ...;
*
ListIterator iterator = list.ListIterator();
*
...
*
while (iterator.hasnext()) {
*
Object obj = iterator.next();
*
// usa obj...
*
if (obj ... non va bene)
*
iterator.remove();
*
iterator.next();
*
Object o = new Object(...);
*
iterator.add(o);
*
}
* @author L.Ferrari
* @version 1.0 del 24.3.2003
*/
public class ListaCollegata
{
/** Classe interna privata, non viene restituita da alcun metodo della
* classe esterna pubblica
*/
private class Elemento {
public Object dato;
public Elemento next;
}
// Classe pubblica
private Elemento primo;
/** Costruttore */
public ListaCollegata() {
primo = null;
}
/** restiuisce il primo elemento della lista */
public Object getTesta() {
if (primo == null) throw new NoSuchElementException();
return primo.dato;
}
/** inserisce in testa */
public void addTesta(Object obj) {
Elemento nuovo = new Elemento();
nuovo.dato = obj;
nuovo.next = primo;
primo = nuovo;
}
/** toglie dalla testa restituendo l'oggetto rimosso */
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 75 -
LF Java Handbook
public Object removeTesta() {
if (primo == null) throw new NoSuchElementException();
Object obj= primo.dato;
primo=primo.next;
return obj;
}
/** crea un iteratore per la lista */
public Iteratore listIterator() {
return new Iteratore();
}
/** definisce un iteratore sulla lista.
* E' una classe interna ma pubblica, per accedervi occorre farvi
* riferimento come ListaCollegata.Iteratore
* Il concetto di iteratore e' un pattern.
*/
public class Iteratore {
public Elemento corrente;
public Elemento precedente;
public Iteratore() {
corrente = null;
precedente = null;
}
public Object next() {
if (corrente == null) {
corrente = primo;
return getTesta();
} else {
if (corrente.next == null) throw new NoSuchElementException();
precedente = corrente;
// serve per remove
corrente = corrente.next;
return corrente.dato;
}
}
public boolean hasNext() {
if (corrente == null)
// iteratore appena creato:
return primo != null;
// esiste next se lista non e' vuota
// altrimenti next esiste se lista non finita
return corrente.next != null;
}
public void add(Object oggetto) {
if (corrente == null) addTesta(oggetto);
Elemento nuovo = new Elemento();
nuovo.dato = oggetto;
nuovo.next = corrente.next;
corrente.next = nuovo;
corrente = nuovo;
precedente = null;
}
/** in base alla definizione di remove non e' permesso chiamare due
*
volte di seguito remove (non si saprebbe come recuperare il
*
precedente del precedente)
*/
public void remove() {
if (corrente == primo) removeTesta();
else {
if (precedente == null) throw new IllegalStateException();
precedente.next=corrente.next;
corrente=precedente;
}
precedente = null;
}
}
public static void main (String[] args) {
ListaCollegata lista = new ListaCollegata();
lista.addTesta("Ernesto");
lista.addTesta("Clara");
lista.addTesta("Davide");
lista.addTesta("Mario");
ListaCollegata.Iteratore it = lista.listIterator();
it.next();
// M|DCE
it.next();
// MD|CE
it.add("Giuseppe");
// MDG|CE
it.add("Felicina");
// MDGF|CE
it.next();
// MDGFC|E
it.remove();
// MDGF|E
// stampa tutti gli elementi
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 76 -
LF Java Handbook
it = lista.listIterator();
while(it.hasNext())
System.out.println(it.next());
}
}
19.2. Algoritmi matematici
19.2.1. Potenza n-esima di numero reale (metodo degli invarianti di ciclo)
Alternativa alla moltiplicazione n volte di a: si utilizza il metodo degli Invarianti di ciclo:
algoritmo (equivale a Math.pow (a, n))
double a=...;
int n=...;
double r = 1;
double b = a;
int i = n;
while (i > 0) {
if ( i%2 == 0) {
b = b * b;
i = i / 2;
} else {
r = r * b;
i--;
}
} //risultato in r, che vale a^n
Esempio: se n= 100 fa tutto utilizzando 10 moltiplicazioni anziche' 100.
Cenni di dimostrazione:
• All'inizio del ciclo while vale la relazione r * b^i = a^n
• Per ogni ciclo, questa relazione e' sempre verificata, solo che via via cresce r e diminuisce
b^i.
• Alla fine il termine b^i diventa b^0, cioe' 1, e r contiene il risultato!
19.2.2. Calcolo della radice quadrata
Preso da C. Horstmann, Debug_Java2.pdf.
Si usa il metodo delle approssimazioni successive, conosciuto gia' ai tempi degli antichi greci.
Si deve trovare sqrt(a).
Si parte da un valore di tentativo x = a e si considerano le quantita' x e a/x.
Se x < sqrt(a) allora a/x > a/sqrt(a), che e' uguale a sqrt(a): x < sqrt(a) < a/x.
Analogamente, se x > sqrt(a) allora a/x < a/sqrt(a) = sqrt(a): x < sqrt(a) < a/x.
Si ottine lo stesso risultato: la radice e' compresa tra x e a/x.
Si puo' avvicinare la soluzione prendendo come nuovo x il valore mediano tra x a a/x e
ripetere il procedimento.
Ci si ferma quando la differenza tra tentativi successivi e' un valore molto piccolo.
19.2.3. Calcolo di pi greco con l'ago di Buffon
(Georges-Louis Lecrerc de Buffon, 1707-1788, naturalista francese) Si lascia cadere molte un
ago lungo un pollice su foglio di carta a righe, spaziate di due pollici, contando un centro se
l'ago interseca una qualunque riga.
Il quoziente tra tentativi e centri e' prossimo a pi greco.
Simulazione: Basta considerare una piccola parte del foglio, con le ordinate che partono da 0
e arrivano a 3. Le righe sono in corrispondenza di 0 e di 2.
- 77 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
La posizione x e' irrilevante; per la posizione dell'ago si puo' partire da una estremita' ylow e
dall'angolo formato con le ascisse (0-180).
La posizione yhigh si calcola come ylow + sin(alfa).
Si fa centro se yhigh e' almeno uguale a 2.
Programma Buffon.java
import java.util.Random
public class Buffon
{
public static void main (String[] args)
{
Random generator = new Random();
int hits =0
final int NTRIES = 10000;
for (int i = 1; i <= NTRIES; i++){
// simula il lancio dell'ago: ylow in (0-2), angle in (0-180)
double ylow = 2 * generator.nextDouble();
double angle = 180 * generator.nextDouble();
// calcola il punto in alto dell'ago
double yhigh = ylow + Math.sin(Math.toRadians(angle));
if (yhigh >= 2)
hits++;
}
// stampa il valore trovato presunto di pi greco
System.out.println("tentativi/successi = "
+ (NTRIES * 1.0) / hits);
}
}
- 78 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
20. ARGOMENTI AVANZATI DI JAVA
20.1. Riflessione
Permette di agire sulle classi e sul loro comportamento.
20.2. Riflessione e classi Proxy
Le classi prosy sono delle classi che si mettono in mezzo tra la classe chiamante e la classe
chiamata per aggiungere delle funzionalita' senza modificare la classe di partenza.
Un esempio puo' essere di aggiungere funzionalita' di tracing, di serializzazione (per produrre
la versione di programma che non salva su file e quella che salva su file), di sincronizzazione...
E' possibile anche utilzzare piu' proxy in cascata sulla classe target (quella nascosta).
Se si usa la riflessione occorrera' pero' usare delle classi Factory.
20.2.1. Uso di classi proxy per il trace
Tracing: per ogni classe si vuole eseguire, se richiesto, il tracing di ogni chiamata di metodo
(parametri di ingresso e valore di ritorno).
Scopo e' quello di abilitare e disabilitare il tracing di qualunque classe del sistema senza
dover aggiungere codice alle classi o senza dover tenere allineate le classi e delle loro
sottocloassi che per ogni metodo eseguono il tracing dell'input e del valore di ritorno.
Vedere il documento pdf: Ira R. Forman, Nate Forman - Java Reflection in Action - cap. 4:
Using Java's dynamic proxy. (Free excerpt, ho versione stampata).
- 79 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
21. FONDAMENTI DELLA PROGRAMMAZIONE AD
OGGETTI
21.1. Oggetti e classi
Scopo: definire i concetti di oggetto, classe, metodo senza entrare nella sintassi di Java.
Esempi:
• 1.: forme grafiche che possono essere disegnate interattivamente
• 2.: iscrizione degli studenti ad una classe
21.1.1. Argomenti
• Definizioni
• Creazione di oggetti
• Chiamata di metodi
• Parametri
• Tipi di dati
• Istanze multiple
• Stato
• Cosa c'e' in un oggetto
• Interazione tra gli oggetti
• Codice sorgente
• Valore di ritorno
• Oggetti come parametri
21.2. Approfondimenti sulla definizione di classi
Scopo: vedendo la definizione di una classe si investiga su come viene scritto il codice per
determinare il comportamento degli oggetti: come definire gli attributi e implementare i metodi.
Esempio:
• macchina distributrice di biglietti
21.3. Interazione tra oggetti
Scopo: si vede come gli oggetti possono collaborare invocando i metodi di altri oggetti per
realizzare uno scopo comune.
Esempi:
• orologio digitale con due implementazioni di display a due cifre
• similazione di un sistema di gestione di e-mail
21.4. Raggruppamenti (collezioni) di oggetti
Scopo: introdurre le collezioni di oggetti e le istruzioni per la gestione dei cicli. I vettori come
tipo particolare di collezioni di oggetti.
Esempi:
• blocco note elettronico
• analizzatore di web-log
- 80 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
21.5. Librerie e documentazione
Scopo: introdurrre le classi standard di Java, vedendo anche come leggere e capire la
documentazione delle librerie.
Importanza della documentazione nello sviluppo di programmi.
Esempi:
• sistema di dialogo Eliza-like
• simulazione grafica di una palla che rimbalza
21.6. Test e debug
Scopo: definire un insieme di regole per produrre classi corrette, comprensibili e facilmente
manutebili. Per fare questo si discutono gli stili di scrittura del codice e dei commenti, le
strategie di testing e di debugging Esempi:
• agenda degli appuntamenti
• calcolatrice elettronica
21.7. Disegno di classi
Scopo: spiegare come si puo' dividere un problema in classi per consentire l'implementazione
di una soluzione.
Si parla di disegno responsibility-driven, accoppiamento, coesione, refactoring.
Esempi:
• gioco interattivo di tipo adventure game (RPG, Role Player Game)
21.8. Ereditarieta' e polimorfismo
Scopo: capire ereditarieta', sottotipi, chiamata di metodi polimorfici, overriding di metodi.
Esempi:
• database di CD
21.9. Tecniche avanzate di astrazione: interfacce e classi astratte
Scopo: approfondire il concetto di ereditarieta' introducendo le classi astratte e le interfacce
Esempi:
• simulazione del sistema prede-predatori
21.10. Gestione degli errori
Scopo: introdurre la gestione degli errori Esempio:
• estensione dell'esempio sull'agenda elettronica
21.11. Disegno di applicazioni
Scopo: strutturare uno scenario definito vagamente in classi e metodi.
I problemi trattati vanno dalla identificazione delle classi, di come devono interagire tra di loro
e di come devono essere distribuite le responsabilita'.
Esempio:
• sistema di prenotazione dei posti al cinema.
21.12. Esercizi sui cicli
• 1.: Itinerario casuale: simulare il percorso di un ubriaco che svolta a caso in un reticolo di
- 81 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
strade di 10 righe orizzontali e 10 verticali.
Dopo 100 svolte calcolare la distanza dal centro.
Ci si aspetterebbe che non possa andare da nessuna parte, invece ci sono buone
probabilita' che la persona esca da qualunque regione circoscritta con un adeguato numero
di tentativi.
• 2.: Traiettoria di un proiettile (simulazione, piu' efficace delle formule perche' consente di
tenere conto del vento e della diversa forza di gravita' alle diverse altezze)
• 3.: Serie di Fibonacci (f1=1, f2=1, f(n) = f(n-1) + f(n-2) per n > 2
• 4.: Calcolo di e^x con la formula 1 + x + (x^2/2!) + (x^3/3!) +... Si termina quando la
differenza tra due valori successivi e' inferiore a un milionesimo del valore stesso.
• 5.: Calcolo di pi greco con le gocce sul foglio quadrato: si espone alla pioggia un foglio di
carta quadrato con inscritto un cerchio di diametro pari al lato del foglio. Il valore di pi greco
e' ricavabile considerando il numero delle gocce cadute nelle due figure (quadrato e
cerchio) proporzionale alle aree...
Suggerimento: considerare il cerchio centrato in 0,0 e il quadrato con angoli nei punti 1,1 e
-1,-1.
• 6.: Grafico di una funzione in Java: disegnare 100 punti individuati dalle coppie (x, f(x)) e
(x+d, f(x+d)) con x compreso tra x1 e x2 e d = (x2-x1)/100: utilizzare la funzione:
f(x) = x^3/100 +-x + 10 e x1= -10, x2 =10
• 7.: Rosa dei venti: disegnarla usando le coordinate polari r=cos(2*teta), con teta compreso
tra 0 e 360; 100 iterazioni.
I valori di x e y valgono x = r cos(teta) e y = r sen(teta).
Provare a trovare un metodo per variare il numero dei petali.
- 82 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
22. DOCUMENTAZIONE
22.1. Cay Horstmann, Big java
a.
b.
c.
d.
e.
f.
g.
h.
i.
j.
k.
l.
m.
Introduzione
Introduzione alle classi e agli oggetti
Tipi di dato fondamentali
Applets e grafica
Decisioni (if)
Iterazioni
Disegno delle classi
Test e debug
Interfacce e polimorfismo
..
..
Graphical User Interface
..
22.2. Cay Horstmann, Concetti di informatica e fondamenti di java 2
ATTENZIONE: nel libro non sono compresi i thread...
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Introduzione
Tipi di dato fondamentali
Classi
Applets e grafica
Decisioni (if)
Iterazioni
Ancora sui metodi
Test e debug
Ereditarieta'
gestione degli eventi
Array e vettori
Graphical User Interface
Flussi ed eccezioni
Progettazione orientata agli oggetti
Algoritmi
Introduzione alle strutture dati
- 83 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
23. API LF
Si trovano sotto Projects\Luigi\LFCommon\java.
Documentazione in formato javadoc. (lfapi.doc\index.html)
23.1. lfapi package
Esiste bldjar.bat che crea la libreria.
I
progetti
che
la
utilizzano
devono
includere
nel
loro
classpath
d:\user\Luigi\Projects\LFcommon\lib\lfapi.jar per utilizzare le classi nei .java deve esserci:
import lfapi.*;
23.1.1. ConfigFile
Gestisce i file di configurazione delle variabili di una applicazione Una linea di definizione di
un parametro ha la forma:
nome=valore # eventuale commento.
Le linee vuote, inizianti con '#' o che non contengono '=' sono ignorate.
23.1.2. ConnectionManager
Stabilisce la connessione con il database server.
23.1.3. cpfile
Sembra non essere quella corretta (vedi txtfile)
23.1.4. EnvironmentMap
Definisce una mappa univoca per l'applicazione in cui tutte le classi possono depositare
coppie chiave-valore.
Esempio di uso:
EnvironmentMap config = EnvironmentMap.getMap();
config.put("CHIAVE 1","Valore1");
config.put("chiave2", new Integer(800));
config.put("Chiave3", "10");
String valore1 = (String)(EnvironmentMap.getMap().get("CHIAVE 1"));
int val1 = config.get("Chiave2"); // da verificare
int val3 = Integer.parseInt((String)config.get("Chiave3"));
String confString= "Configuration parameters:\n";
Set keyValues = config.entrySet();
Iterator it = keyValues.iterator();
while(it.hasNext()) {
Map.Entry entry=(Map.Entry)it.next();
confString+= "
" + entry.getKey()
+ " = "+entry.getValue()+ "\n";
}
Usa il pattern Singleton.
23.1.5. FileInputHashMap
23.1.6. FileUtility
23.1.7. Log
Esistono anche delle funzioni predefinite in java, vedi Java Tech Tip.
23.1.8. StringUtility
- 84 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
23.1.9. ThumbnailBuilder
Crea il thumbnail di una immagine JPEG, consentendo di specificare dimensioni massime e
qualita' della riduzione. Un programma di esempio e' miniatore (dalla versione 1.01 in avanti)
23.1.10. ThumbnailSetBuilder
Crea i thumbnail di tutte le immagini in una directory e nelle sue sottodirectory.
Usa ThumbnailBuilder.
23.1.11. txtfile
Gestione file di testo
23.1.12. URLReader
Contine funzioni di utilita' per la gestione di URL.
In particolare:
• getHashMap: Interpreta il contenuto dell'URL come se si trattasse di un file di
configurazione delle variabili di una applicazione.
• readline: Legge una linea dall'URL.
23.2. lfapi.GUI package
23.2.1. ErrorWindow
Apre una finestra mostrando la stringa e l'eventuale eccezione.
23.2.2. GenericTablePanel
Fornisce funzioni aggiuntive per creare pannelli a partire da tabelle. Occorre definre una
classe che faccia da modello di tabella.
Utilizzare l'esempio fornito ExampleTableModel.
23.2.3. FormLayout
Layout per la gestione di form
23.2.4. StatusBar
Crea un testo da inserire nei pannelli con testo modificabile.
- 85 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
24. ESEMPI DI CODICE
24.1. JTable con diverse funzionalita'.
Utilizza TableModel. Si tratta di una serie di scatole una dentro l'altra; in due casi ci sono dei
pattern decorator. Implementa il pattern MVC (model = Table model, view = JTablePopup e
JTable inclusa).
+-------------------------------------------------+
| JDatiPanel
|
|
+-------------------+
|
|
| JScrollPane
|
|
|
+-------------------+
|
|
|
|
|
usa
|
|
|
|
|
v
|
| +-------------------+
+---------------+ |
| |SortFilterModel
|
|JTablePopup
| |
| | +--------------+ |
| +----------+ | |
| | |DatiTableModel| |
| |JTable
| | |
| | |
| |
| |
(model)| | |
| | |
| |
| |
|
| | |
| | |
| | <--------------+
| | |
| | |
| |
| |
| | |
| | +--------------+ |
| +----------+ | |
| +-------------------|
+---------------+ |
|
|
+-------------------------------------------------+
Consente:
• Scroll su numero di record maggiore di quelli visualizzabili (pattern Decorator)
• Cambio dell'ordine di visualizzazione delle colonne (trascinando il titolo)
• Ordinamento in base ai dati di una colonna (click sul titolo, pattern Decorator)
• Autoresize delle colonne (c'e' del codice cablato forse da sistemare)
• Pop-up menu' sul singolo record con attivazione di eventi che modificano i dati del record e
lo rivisualizzano aggiornato
• Refresh della JTable dopo TIMEOUT secondi
Esempio di riga da mostrare nella JTable (src/JTable/Dato.java)
/**
* Classe di esempio per i dati da visualizzare
*/
import javax.swing.*;
import java.awt.*;
public class Dato {
String str;
int num;
boolean flag;
public Dato (int n, String s, boolean f) {
str = s;
num = n;
flag = f;
}
public String toString() {
return num+" "+str+" "+flag;
}
public int getNum() { return num;}
public String getStr() { return str;}
public boolean getFlag() { return flag;}
public void setFlag(boolean f) { flag = f;}
public Object[] getValues(int size) {
Object[] row = new Object[size];
try{
// WARNING
- 86 -
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
if (size==3) {
row[0] = new Integer(num);
row[1] = str;
row[2] = new Boolean(flag);
}
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Dato: Invalid size " + size);
System.exit(1);
}
return row;
}
public JPanel toJPanel(){
JPanel jp = new JPanel();
JLabel title = new JLabel("Dato "+str);
JLabel info = new JLabel("Numero "+ num +"\n" +
"Stringa: " + str +"\n" +
"Flag: " + flag +"\n" );
jp.setLayout(new BorderLayout());
jp.setPreferredSize(new Dimension(600,580));
jp.setMinimumSize(new Dimension(600,580));
jp.add(title, BorderLayout.NORTH);
jp.add(info, BorderLayout.SOUTH);
return jp;
}
}
Il pannello che contiene la JTable (src/JTable/DatoTablePanel.java)
/**
* Create a viewer for a generic table
*
* @author L. Ferrari - [email protected]
* @version 1.0 21.9.2004
* @history 1.0 Versione originale
*/
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.*;
java.awt.event.*;
java.applet.*;
javax.swing.*;
java.sql.*;
java.util.*;
javax.swing.table.*;
java.io.StringWriter;
java.io.PrintWriter;
java.sql.*;
java.net.*;
java.io.File;
public class DatoTablePanel extends JPanel {
private static int PANELMINX=500;
private static int PANELMINY=100;
JScrollPane scrollPane = new JScrollPane();
JTablePopup jTable;
JPopupMenu jPopupMenu;
public DatoTablePanel(JPopupMenu pum) {
super();
this.jPopupMenu=pum;
scrollPane.setBorder(null);
scrollPane.setMaximumSize(new Dimension(PANELMINX, PANELMINY));
scrollPane.setMinimumSize(new Dimension(PANELMINX, PANELMINY));
scrollPane.setOpaque(false);
scrollPane.setPreferredSize(new Dimension(PANELMINX, PANELMINY));
this.add(scrollPane,
new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.SOUTH, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
}
- 87 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
/* ----------------------------------------------------------------------------------* Fill input table and put it into table
* non va bene se richiamata perche' fa perdere allineamenti.
*/
public void createViewerTable(ArrayList data, ArrayList titles) {
// Create table
jTable = new JTablePopup(jPopupMenu);
try {
DatiTableModel tm = new DatiTableModel(data, titles);
SortFilterModel sfm = new SortFilterModel(tm);
// Displaying Table
jTable.setModel(sfm);
jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jTable.setIntercellSpacing(new Dimension(5,0));
jTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// AUTO RESIZE SECTION
for (int col=0; col < jTable.getColumnCount(); col ++) {
// Max caratteri:
int maxLength =
jTable.getColumnName(col).length(); //init con lun. nome
for (int i=0; i < jTable.getRowCount(); i++)
if (maxLength < String.valueOf(jTable.getValueAt(i,col)).length())
maxLength = String.valueOf(jTable.getValueAt(i,col)).length();
TableColumn cm = jTable.getColumn(jTable.getColumnName(col));
maxLength += 7;
cm.setMaxWidth(maxLength*6);
if (col == jTable.getColumnCount()-1)
cm.setMaxWidth(630);
//cm.setMinWidth(maxLength*6);
cm.setMinWidth(6); //Per un resize da user
cm.setPreferredWidth(maxLength*6);
cm.setWidth(maxLength*6);
/* DA FARE
if(rs.getMetaData().getColumnTypeName(col+1).equals("NUMBER")) {
DefaultTableCellRenderer dtcr = new DefaultTableCellRenderer();
dtcr.setHorizontalAlignment(JTextField.RIGHT);
cm.setCellRenderer(dtcr);
}
*/
}
scrollPane.getViewport().add(jTable, null);
// Resize ultima colonna:
if (jTable.getSize().getWidth() < 600.0)
jTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
//this.validate();
// END AUTO RESIZE SECTION
sfm.addMouseListener(jTable);
jTable.setDragEnabled(true);
} catch (Exception e) {
new ErrorWindow("ProcessTablePanel: CreateViewerTable",e);
return;
}
this.validate();
}
/* --------------------------------------------------------------------------------* Modello della jTable
*/
class DatiTableModel extends javax.swing.table.AbstractTableModel {
private ResultSet rs;
private java.util.AbstractList cache;
private ArrayList titles;
public DatiTableModel(ArrayList data, ArrayList titles) {
this.titles=titles;
cache = new java.util.ArrayList();
int cols = titles.size();
Iterator it = data.iterator();
while (it.hasNext()) {
Object[] row = new Object[cols];
Dato p = (Dato)it.next();
row = p.getValues(cols);
cache.add(row);
}
}
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 88 -
LF Java Handbook
public String getColumnName(int col) {
try {
return (String)titles.get(col);
} catch (Exception e) {
System.err.println("GetColumnName: "+e);
return "";
}
}
public int getColumnCount() {
try {
return titles.size();
} catch (Exception e) {
System.err.println("GetColumnCount: "+e);
return 0;
}
}
public Object getValueAt(int row, int col) {
if (row < cache.size())
return ((Object[])cache.get(row))[col];
else
return "";
}
public int getRowCount() {
return cache.size();
}
}
/* --------------------------------------------------------------------------------* Bridge class per implementare il sorting automatico cliccando sulle colonne
*/
class SortFilterModel extends AbstractTableModel {
private class Row implements Comparable {
public int index;
public int compareTo(Object other) {
Row otherRow = (Row)other;
Object a;
try {
a = model.getValueAt(index,sortColumn);
} catch (ArrayIndexOutOfBoundsException i) {a = "";}
if (a == null) a = "";
Object b;
try {
b = model.getValueAt(otherRow.index, sortColumn);
} catch (ArrayIndexOutOfBoundsException i) {b = "";}
if (b == null) b = "";
if (a instanceof Comparable)
return ((Comparable)a).compareTo(b);
else return index - otherRow.index;
}
}
private Row[] rows;
private TableModel model;
private int sortColumn;
public SortFilterModel (TableModel m) {
model = m;
rows = new Row[model.getRowCount()];
for (int i = 0; i < rows.length; i++) {
rows[i] = new Row();
rows[i].index = i;
}
}
public void sort (int c) {
sortColumn = c;
Arrays.sort(rows);
fireTableDataChanged();
}
public void addMouseListener(final JTable table) {
table.getTableHeader().addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent event) {
//if (event.getClickCount() < 2) return;
int tableColumn = table.columnAtPoint(event.getPoint());
int modelColumn = table.convertColumnIndexToModel(tableColumn);
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 89 -
LF Java Handbook
sort(modelColumn);
}
});
}
public Object getValueAt(int r, int c) {
return model.getValueAt(rows[r].index,c);
}
public boolean isCellEditable(int r, int c) {
return model.isCellEditable(rows[r].index,c);
}
public int getRowCount() {
return model.getRowCount();
}
public int getColumnCount() {
return model.getColumnCount();
}
public String getColumnName(int c) {
return model.getColumnName(c);
}
public Class getColumnClass(int c) {
return model.getColumnClass(c);
}
}
/*
----------------------------------------------------------------------------------------* Classe che realizza la gestione del mouse per le funzioni pop-up
*
*/
class JTablePopup extends JTable {
JPopupMenu jPopupMenu;
public JTablePopup(JPopupMenu pum) {
super();
this.jPopupMenu=pum;
this.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) popupShow(e);
}
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) popupShow(e);
}
public void mouseClicked(MouseEvent e) {
if (e.isPopupTrigger()) popupShow(e);
}
});
}
private void popupShow (MouseEvent e) {
//System.out.println("JablePopup - popupShow Row: "+this.getSelectedRow());
if (this.getSelectedRow()!= -1) {
jPopupMenu.show(this, e.getX(), e.getY());
}
}
}
/** --------------------------------------------------------------------------------------* Classe per la gestione degli errori
*/
private class ErrorWindow extends JOptionPane {
public ErrorWindow (String s, Exception e ) {
String text = s + "\n\n";
if (e!= null) {
text+= e + "\n";
StringWriter out = new StringWriter();
e.printStackTrace(new PrintWriter(out));
text += out.toString();
}
showMessageDialog(null, text,
"JTable Test Error Window",
JOptionPane.WARNING_MESSAGE);
}
public ErrorWindow ( Exception e ) {
this("Exception",e);
}
public ErrorWindow ( String s) {
this(s,null);
}
}
- 90 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
}
Classe di lancio con GUI (src/JTable/DatoTablePanelTest.java)
import
import
import
import
import
import
import
import
import
import
java.awt.*;
java.awt.event.*;
java.awt.event.KeyEvent;
javax.swing.KeyStroke;
java.applet.*;
javax.swing.*;
java.sql.*;
java.net.*;
java.io.File;
java.util.*;
public class DatoTablePanelTest extends JApplet {
DatiList listaDati;
// list of data
String user;
boolean debug = true;
String AppletURL = null;
String imagesPath = "";
String img;
// MenuBar and Menu
JMenuBar jMasterMenu = new JMenuBar();
JMenu jMenuFile;
JMenu jMenuDato;
JMenu jMenuHelp;
JPopupMenu jPopupMenu;
static boolean isStandalone = false;
static String windowTitle = "JTable tester - Copyright (C) Luigi Ferrari";
boolean popupMenuEnabled = true;
private
private
private
private
private
JPanel mainPanel = new JPanel();
JPanel messagePanel = new JPanel();
DatoTablePanel datiPanel;
JTextField statusBar = new JTextField();
LinkedHashMap config = new LinkedHashMap();
// Applet parameters
int requestedWidth = 0;
int requestedHeight = 0;
/* ----------------------------------------------------------* getParameter
*/
public String getParameter(String key, String def) {
return isStandalone ? System.getProperty(key, def) :
(getParameter(key) != null ? getParameter(key) : def);
}
/* ----------------------------------------------------------* PopupMenuEnable
*/
public boolean getPopupMenuEnabled () { return this.popupMenuEnabled; }
public void setPopupMenuEnabled (boolean b) { popupMenuEnabled = b; }
/* ----------------------------------------------------------* Init / start /stop
*/
public void init() {
//default config values
config.put("WIDTH",new Integer(800));
config.put("HEIGH",new Integer(600));
config.put("TIMEOUT","60");
// timeout in secondi
config.put("VERSION","1.0.0");
config.put("DEBUG", "true");
// reading parameters if running as applet.
if (!isStandalone) {
String windowWidthString = getParameter("WINDOWWIDTH");
if (windowWidthString != null) {
- 91 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
try {
requestedWidth = Integer.parseInt(windowWidthString);
config.put("WIDTH",new Integer(requestedWidth));
} catch (NumberFormatException e) {
//Use default width.
}
}
String windowHeightString = getParameter("WINDOWHEIGHT");
if (windowHeightString != null) {
try {
requestedHeight = Integer.parseInt(windowHeightString);
config.put("HEIGH",new Integer(requestedHeight));
} catch (NumberFormatException e) {
//Use default height.
}
}
String deb = getParameter("DEBUG");
if (deb != null) {
deb=deb.toLowerCase();
if(deb.equals("true")||deb.equals("false"))
config.put("DEBUG", deb);
}
}
// set debug
debug=(config.get("DEBUG").equals("true")?true:false);
if ((requestedWidth > 0) | (requestedHeight > 0)) {
this.resize(Math.max(requestedWidth,this.getSize().width),
Math.max(requestedHeight, this.getSize().height));
}
// read process table
listaDati = new DatiList();
jMenuFile=createMenuFile();
jMenuDato=createMenuDato();
jMenuHelp=createMenuHelp();
jPopupMenu=createPopupMenuDato();
jMasterMenu.add(jMenuFile);
jMasterMenu.add(jMenuDato);
jMasterMenu.add(Box.createHorizontalGlue());
jMasterMenu.add(jMenuHelp);
datiPanel = new DatoTablePanel(jPopupMenu);
datiPanel.setMinimumSize(
new Dimension(200, 300));
datiPanel.createViewerTable(listaDati.getData(),
listaDati.getTitles());
statusBar.setText("Welcome to JTable tester.");
statusBar.setEditable(false);
statusBar.setHorizontalAlignment(SwingConstants.LEFT);
statusBar.setBackground(Color.WHITE);
messagePanel.setMinimumSize(
new Dimension(300, 20));
messagePanel.setPreferredSize(
new Dimension(300, 20));
messagePanel.setBackground(Color.RED);
messagePanel.setLayout(new BorderLayout());
messagePanel.add(statusBar,BorderLayout.SOUTH);
mainPanel.add(datiPanel,BorderLayout.CENTER);
mainPanel.setBackground(Color.YELLOW);
mainPanel.add(messagePanel,BorderLayout.SOUTH);
this.getContentPane().add(mainPanel, BorderLayout.CENTER);
this.setJMenuBar(jMasterMenu);
// il codice seguente e' replicato in repaint
// perche' le JTable sono ricreate nuove...
/*
datiPanel.jTable.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (datiPanel.jTable.getSelectedRow()!=-1) {
enableDatoMenu();
}
}
public void mouseReleased(MouseEvent e) {
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 92 -
LF Java Handbook
if (datiPanel.jTable.getSelectedRow()!=-1) {
enableDatoMenu();
}
}
});
*/
// fine codice replicato
this.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) { enableDatoMenu(); }
public void mousePressed(MouseEvent e) { enableDatoMenu(); }
public void mouseClicked(MouseEvent e) { enableDatoMenu(); }
});
}
public void start() {
statusBar.setText("Start..");
repaint();
jMenuFile.setEnabled(true);
jMenuDato.setEnabled(false);
jMenuHelp.setEnabled(true);
class RefreshTimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
refresh();
}
}
ActionListener listener = new RefreshTimerListener();
int millis = Integer.parseInt((String)config.get("TIMEOUT")) * 1000;
System.out.println("Timeout in millisecondi di "+ millis);
javax.swing.Timer t = new javax.swing.Timer(millis, listener);
/* abilitare se si vuole una rilettura dei dati ogni
* TIMEOUT secondi
*/
//t.start();
}
public void stop() {
statusBar.setText("Stop..");
repaint();
}
/** Aggiorna il pannello in base ai dati correnti
*/
public void repaint(){
GregorianCalendar gc = new GregorianCalendar();
System.out.println("" + gc.get(Calendar.HOUR_OF_DAY)+":"+
gc.get(Calendar.MINUTE)+":"+gc.get(Calendar.SECOND)+"."+
gc.get(Calendar.MILLISECOND)+" Repaint.");
Dato d = getSelectedDato();
datiPanel.createViewerTable(listaDati.getData(),
listaDati.getTitles());
if (d!=null) setSelectedDato(d.getStr());
datiPanel.jTable.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (datiPanel.jTable.getSelectedRow()!=-1) {
enableDatoMenu();
}
}
public void mouseReleased(MouseEvent e) {
if (datiPanel.jTable.getSelectedRow()!=-1) {
enableDatoMenu();
}
}
});
super.repaint();
}
/* ------------------------------------------------------------------------* Menu' utilities
*/
private void setMenuItem(JMenuItem i, String text, int key, String icon){
i.setText(text);
i.setMnemonic(key);
//if (icon.length()>0) i.setIcon(createIcon(icon));
}
private void setMenuItem(JMenuItem i, String text, int key){
i.setText(text);
i.setMnemonic(key);
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 93 -
LF Java Handbook
}
/* -------------------------------------------------------------------------* MENU CONSTRUCTORS
*/
public JMenu createMenuFile(){
JMenu menu = new JMenu();
menu.setText("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.add(createPrintMenuItem());
menu.add(createQuitMenuItem());
return menu;
}
public JMenu createMenuDato(){
JMenu menu = new JMenu();
menu.setText("Dato");
menu.setMnemonic(KeyEvent.VK_D);
menu.add(createEnableDatoItem());
menu.add(createDisableDatoItem());
menu.addSeparator();
// DEBUG
menu.add(createProcessInfoItem());
return menu;
}
public JPopupMenu createPopupMenuDato(){
JPopupMenu menu = new JPopupMenu();
menu.add(createEnableDatoItem());
menu.add(createDisableDatoItem());
menu.addSeparator();
// DEBUG
menu.add(createProcessInfoItem());
return menu;
}
public JMenu createMenuHelp(){
JMenu menu = new JMenu();
menu.setText("Help");
menu.setMnemonic(KeyEvent.VK_H);
menu.add(createAboutMenuItem());
return menu;
}
/* Se una delle righe e' selezionata occorre poter lavorare
* anche da menu'
*/
protected void enableDatoMenu() {
if ((datiPanel.jTable.getSelectedRow()!=-1))
jMenuDato.setEnabled(true);
else
jMenuDato.setEnabled(false);
repaint();
}
/* -------------------------------------------------------------------------* MENU ITEMS CONSTRUCTORS
*/
public JMenuItem createPrintMenuItem(){
JMenuItem it = new JMenuItem();
setMenuItem(it, "Print", KeyEvent.VK_P, "Print16");
class PrintMenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
print();
}
}
ActionListener listener = new PrintMenuItemListener();
it.addActionListener(listener);
return it;
}
public JMenuItem createQuitMenuItem(){
JMenuItem it = new JMenuItem();
setMenuItem(it, "Quit", KeyEvent.VK_Q, "Stop16");
class QuitMenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
quit();
}
}
ActionListener listener = new QuitMenuItemListener();
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 94 -
LF Java Handbook
it.addActionListener(listener);
return it;
}
public JMenuItem createEnableDatoItem(){
JMenuItem it = new JMenuItem();
setMenuItem(it, "Enable", KeyEvent.VK_E);
class EnableDatoMenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
setEnable(true);
}
}
ActionListener listener = new EnableDatoMenuItemListener();
it.addActionListener(listener);
return it;
}
public JMenuItem createDisableDatoItem(){
JMenuItem it = new JMenuItem();
setMenuItem(it, "Disable", KeyEvent.VK_D);
class DisableDatoMenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
setEnable(false);
}
}
ActionListener listener = new DisableDatoMenuItemListener();
it.addActionListener(listener);
return it;
}
// DEBUG
public JMenuItem createProcessInfoItem(){
JMenuItem it = new JMenuItem();
setMenuItem(it, "Info", KeyEvent.VK_I);
class DatoInfoItemListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
datoInfo();
}
}
ActionListener listener = new DatoInfoItemListener();
it.addActionListener(listener);
return it;
}
// - DEBUG
public JMenuItem createAboutMenuItem(){
JMenuItem it = new JMenuItem();
setMenuItem(it, "About", KeyEvent.VK_A, "Information16");
class AboutMenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
about();
}
}
ActionListener listener = new AboutMenuItemListener();
it.addActionListener(listener);
return it;
}
/* ------------------------------------------------------------------------* MENU EVENTS PROCESS
*/
protected Dato getSelectedDato() {
String name ="";
if (datiPanel.jTable.getSelectedRow()!=-1)
name = (String)datiPanel.jTable.getModel().getValueAt(
datiPanel.jTable.getSelectedRow(),1);
return listaDati.getDato(name);
}
protected void setSelectedDato(String name) {
int nrow = datiPanel.jTable.getRowCount();
for (int i = 0;i<nrow; i++){
if (datiPanel.jTable.getValueAt(i,1).equals(name)){
datiPanel.jTable.setRowSelectionInterval(i,i);
return;
//esce
}
}
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 95 -
LF Java Handbook
return;
}
protected void refresh () {
Dato d = getSelectedDato();
statusBar.setText("Refresh.. (dato selezionato: "+d.getStr()+")");
/* Se i dati sono acquisiti da server
* puo' essere necessario un aggiornamento...
*/
//listaDati.reload();
repaint();
}
private void print () {
statusBar.setText("Print..");
repaint();
/* ancora da fare
new JOptionPanePrint();
*/
statusBar.setText("Print executed");
repaint();
}
private void quit () {
statusBar.setText("Quit..");
repaint();
System.out.println("Quit..");
System.exit(0);
}
private void setEnable (boolean value) {
System.out.println("SetEnable: Dato "+ getSelectedDato().getStr() + ": "+value);
if (value) {
statusBar.setText("Dato "+ getSelectedDato().getStr() + ": enable");;
} else {
statusBar.setText("Dato "+ getSelectedDato().getStr() + ": disable");
}
getSelectedDato().setFlag(value);
repaint();
}
// DEBUG ------------------------------------------------------------------private void datoInfo () {
statusBar.setText("View " +getSelectedDato().getStr() +" info..");
JPanel p=getSelectedDato().toJPanel();
JRootPane oldRP = this.getRootPane();
JRootPane newRP = new JRootPane();
this.setRootPane(newRP);
JComponent c = (JComponent)this.getContentPane();
c.add (p);
//this.setContentPane(c);
repaint();
JOptionPane.showMessageDialog(null,
"Info for "+getSelectedDato().toString()+" .");
this.setRootPane(oldRP);
repaint();
}
// - DEBUG ---------------------------------------------------------------private void about () {
statusBar.setText("Display about dialog..");
repaint();
JOptionPane jop = new JOptionPane("TEST DELLA JTABLE (C)Luigi Ferrari");
jop.showMessageDialog(null,getAppletInfo());
statusBar.setText("");
repaint();
}
/* ------------------------------------------------------------------------* get Applet Information
*/
public String getAppletInfo() {
String host = "running standalone..";
if (!isStandalone) host =getCodeBase().getHost();
// read config
String confString = "";
// if (((Boolean)config.get("DEBUG")).booleanValue()) {
if (debug) {
confString= "Configuration parameters:\n";
Set keyValues = config.entrySet();
Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
- 96 -
LF Java Handbook
Iterator it = keyValues.iterator();
while(it.hasNext()) {
Map.Entry entry=(Map.Entry)it.next();
confString+= "
" + entry.getKey()
+ " = "+entry.getValue()+ "\n";
}
confString += "Applet URL: "+
(String)this.getParameter("AppletURL","")+"\n";
}
return windowTitle + " \n\n" +
"
Running on: " + host + "\n" +
"
Java class version: " +
System.getProperty("java.class.version") + "\n" +
"
Java version: " + System.getProperty("java.version") + "\n" +
/*
"
HTTP Proxy Host: " + System.getProperty("http.proxyHost") +
"
port: " + System.getProperty("http.proxyPort") + "\n" +
"
HTTPS Proxy Host: " + System.getProperty("https.proxyHost") +
"
port: " + System.getProperty("https.proxyPort") + "\n" +
*/
"
Client operating system architecture: " +
System.getProperty("os.arch")+ "\n" +
"
Client operating system name: " +
System.getProperty("os.name")+ "\n" +
"\n" + confString +
"\nCopyright (C) Luigi Ferrari <[email protected]>, Genova, Italia";
}
/* ---------------------------------------------------------------------------* Gestione combinata applet e frame
*/
public static void main(String args[]) {
isStandalone = true;
JFrame mf = new JFrame(windowTitle);
DatoTablePanelTest aef = new DatoTablePanelTest();
aef.init();
aef.start();
mf.getContentPane().add("Center", aef);
mf.setSize(600,600);
mf.show();
mf.setVisible(true);
}
/**
* Crea una lista di oggetti di tipo Dato
*
* @author L. Ferrari - [email protected]
* @version 1.0 21.9.2004
* @history 1.0 Versione originale
*/
public class DatiList {
private ArrayList data;
// leaf processes
private ArrayList titles;
// titles
public DatiList() {
titles = new ArrayList();
setTitles(titles);
reload();
}
private void setTitles(ArrayList t) {
t.add("NUMERO");
t.add("STRINGA");
t.add("FLAG");
}
public ArrayList getTitles() { return titles; }
public ArrayList getData() { return data; }
/* da rivedere la gestione delle eccezioni
*/
public void reload() {
data = new ArrayList();
// dati per il test
String[] datiDiTest = new String[10];
for(int i=0; i<10; i++)
datiDiTest[i]=""+(100+i+1)+",dato"+(i+1)+","+(i%2==0);
int j=0;
- 97 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
try {
//Legge da qualche parte i dati...
String line="";
StringTokenizer tokenLine;
String s="";
boolean f=false;
int n=0;
// data read
while((line)!=null){
line=datiDiTest[j++]; // dati finti di prova
if (debug) System.out.println("DEBUG: DatiList: read: "+line);
if (line.trim().startsWith("<")) continue;
if (line.length() == 0) continue;
try {
tokenLine = new StringTokenizer(line, ",");
n=Integer.valueOf(tokenLine.nextToken()).intValue();
s=tokenLine.nextToken();
f=tokenLine.nextToken().equals("true");
}catch(NoSuchElementException e) {
//invalid format line
System.out.println("DatiList: Sintax error:\n"
+ "input line= "+line +"\n descarded.");
continue;
}
Dato d = new Dato(n, s, f);
data.add(d);
// per ora...
if(j==10) break;
}
}catch(Exception e) {
System.out.println("DatiList: Found Exception "+e);
}finally{
;
}
}
/** cerca un dato in base alla stringa
*/
public Dato getDato(String str){
Iterator it = data.iterator();
Dato d;
while (it.hasNext()) {
d = (Dato)it.next();
if (d.getStr().equals(str)) return d;
}
return null;
}
}
}
24.2. Form layout
Presi da Horstmann OO Design and Patterns.
Layout per form per l'inserimento dati (src/FormLayout.java)
import java.awt.*;
/**
A layout manager that lays out components along a central axis
*/
public class FormLayout implements LayoutManager
{
public Dimension preferredLayoutSize(Container parent)
{
Component[] components = parent.getComponents();
left = 0;
right = 0;
height = 0;
for (int i = 0; i < components.length; i += 2)
{
Component cleft = components[i];
Component cright = components[i + 1];
Dimension dleft = cleft.getPreferredSize();
- 98 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
Dimension dright = cright.getPreferredSize();
left = Math.max(left, dleft.width);
right = Math.max(right, dright.width);
height = height + Math.max(dleft.height,
dright.height);
}
return new Dimension(left + GAP + right, height);
}
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
public void layoutContainer(Container parent)
{
preferredLayoutSize(parent); // Sets left, right
Component[] components = parent.getComponents();
Insets insets = parent.getInsets();
int xcenter = insets.left + left;
int y = insets.top;
for (int i = 0; i < components.length; i += 2)
{
Component cleft = components[i];
Component cright = components[i + 1];
Dimension dleft = cleft.getPreferredSize();
Dimension dright = cright.getPreferredSize();
int height = Math.max(dleft.height, dright.height);
cleft.setBounds(xcenter - dleft.width, y + (height
- dleft.height) / 2, dleft.width, dleft.height);
cright.setBounds(xcenter + GAP, y + (height
- dright.height) / 2, dright.width, dright.height);
y += height;
}
}
public void addLayoutComponent(String name, Component comp)
{}
public void removeLayoutComponent(Component comp)
{}
private
private
private
private
int left;
int right;
int height;
static final int GAP = 6;
}
Classe di test (src/FormLayoutTester.java)
import java.awt.*;
import javax.swing.*;
public class FormLayoutTester
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setLayout(new FormLayout());
frame.add(new JLabel("Name"));
frame.add(new JTextField(15));
frame.add(new JLabel("Address"));
frame.add(new JTextField(20));
frame.add(new JLabel("City"));
frame.add(new JTextField(10));
frame.add(new JLabel("State"));
frame.add(new JTextField(2));
frame.add(new JLabel("ZIP"));
frame.add(new JTextField(5));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
- 99 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]
LF Java Handbook
}
- 100 Rel. 1.0 del 11.12.2006 - Copyright Luigi Ferrari, [email protected]