Ordine degli Ingegneri Provincia di Catania

1
Java Programming Language
Introduzione al linguaggio di programmazione Java
29 giugno – 7 luglio 2007
Ing. Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
2
Modulo 1
Modulo 1: Introduzione
Questo modulo propone una panoramica generale del linguaggio di programmazione
Java, delle sue principali peculiarità ed introduce le applicazioni in Java.
Vengono illustrati i concetti di classi e di package nonché alcuni dei package Java usati
più comunemente.
Che cosa è il Java?
 Un linguaggio di programmazione
 Un ambiente di sviluppo
 Un Application Environment
 Un deployment Environment
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
3
Modulo 1
Obiettivi principali
Il linguaggio di programmazione Java fornisce:

Un linguaggio facile con cui programmare.
•
Elimina l’aritmetica dei puntatori e la gestione della memoria che hanno effetti sulla
robustezza del codice.
•
E’ orientato agli oggetti per aiutare il programmatore a modellizzare i programmi in
termini di “mondo reale”.
•
Fornisce una metodologia per produrre codice nella maniera più semplice e chiara
possibile.

Un ambiente interpretato che si traduce nei due seguenti benefici:
•
Velocità di sviluppo – Elimina la sequenza compile-link-load-test.
•
Portabilità del codice.

Una modalità per i programmi di eseguire più di un thread contemporaneamente.

Una modalità per modificare i programmi dinamicamente durante la loro esecuzione
consentendo loro di caricare e scaricare moduli di codice.

Una modalità per controllare i moduli caricati per assicurarne la sicurezza nella loro
esecuzione.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
4
Modulo 1
Obiettivi principali
L’architettura della tecnologia Java usa i seguenti tre concetti
seguenti per raggiungere gli obiettivi elencati:
 La Java Virtual Machine (JVM)
 La Garbage Collection
 La sicurezza del codice
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
5
Modulo 1
La Java Virtual Machine
La specifica della Java Virtual Machine definisce la virtual machine come:
Una macchina immaginaria implementata emulandola via software in una
macchina reale. Il codice per la Java Virtual Machine è memorizzato in uno
o più file .class, ciascuno dei quali contiene il codice almeno per una public
class.
La specifica per la JVM fornisce le specifiche per le piattaforme hardware in cui
tutto il codice Java è compilato. Queste specifiche abilitano il software Java ad
essere “platform independent” poiché la compilazione è effettuata per una
macchina generica nota come Java Virtual Machine (JVM). Questa “macchina
generica” può essere emulata via software, per poter eseguire programmi nei vari
sistemi già esistenti, oppure implementata via hardware.
Il compilatore legge il codice sorgente della applicazione in Java e genera del
bytecode. I Bytecode sono istruzioni in codice macchina per la JVM. Ogni
interprete Java, non importa che sia un tool di sviluppo Java o un browser web
che esegue delle applets, ha una propria implementazione della JVM.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
6
Modulo 1
Garbage Collection
Molti linguaggi di programmazione consentono l’allocazione dinamica della memoria durante
l’esecuzione dei programmi. Il processo di allocazione della memoria varia in funzione della sintassi
del linguaggio, ma in tutti i casi produce un puntatore all’indirizzo iniziale di un blocco di memoria.
Una volta che la memoria allocata non è più necessaria (il puntatore che referenzia la memoria è andato
out of scope), il programma o l’ambiente di esecuzione (runtime environment) dovrebbe liberare la
memoria.
In C, C++ ed in altri linguaggi, lo sviluppatore del programma è responsabile della deallocazione della
memoria. Questo potrebbe essere talvolta un compito oneroso, non essendo sempre noto in anticipo
quando la memoria debba essere rilasciata. I programmi che non provvedono a deallocare la memoria
non più necessaria inevitabilmente si bloccano quando non c’è più memoria disponibile da allocare.
Il Java solleva il programmatore dalla responsabilità di deallocare la memoria. Esso fornisce un thread
(sottoprocesso) al livello di sistema che tiene traccia di tutte le allocazioni della memoria. Durante i
cicli di pausa della JVM, il thread della garbage collection effettua un controllo sulla memoria allocata
e libera tutta quella non più necessaria.
La Garbage Collection avviene automaticamente lungo tutta la durata della esecuzione di un
programma in Java, eliminando la necessità di deallocare la memoria ed evitando “memory leaks”
(perdite di memoria). D’altra parte, gli schemi della garbage collection possono variare in maniera
consistente tra diverse implementazioni della JVM.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
7
Modulo 1
Sicurezza del codice
Il Java Runtime Environment:
 Carica il codice – “class loader”
Il class loader carica tutte le classi necessarie per l’esecuzione di un programma, ne
aumenta la sicurezza separando i “namespaces” (spazio dei nomi) per le classi sul file
system locale da quelle importate da sorgenti in rete. Questo limita ogni tipo di
applicazione “Trojan horse” poiché le classi locali hanno sempre la precedenza ad essere
caricate.
 Verifica il codice – “bytecode verifier”
Il codice Java deve superare diversi test prima di poter essere eseguito sul proprio
calcolatore. La JVM passa il codice attraverso un “bytecode verifier” che intercetta il
formato dei frammenti di codice illegale che modificano i puntatori, violano i permessi
di accesso agli oggetti o tentano di cambiare il tipo degli oggetti.
 Esegue il codice – “runtime interpreter”
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
8
Modulo 1
Una semplice applicazione Java
1.
2.
3.
4.
5.
6.
7.
8.
//
// Sample HelloWorld application
//
public class HelloWorldApp{
public static void main (Strings args [])
System.out.println(“Hello World!”);
}
}
{
Queste linee sono lo stretto necessario per stampare sullo schermo la frase “Hello World!”.





public – Il metodo main() può essere chiamato da chiunque, incluso l’interprete Java (dalla riga di comando).
static – Indica al compilatore che il metodo main() è utilizzabile nel contesto della classe HelloWorldApp e
dovrebbe essere eseguito prima di ogni altro metodo o istruzione.
void – Indica the il metodo main() non ritorna niente.
Questo è importante perché Java effettua un attento controllo dei tipi per confermare che il metodo chiamato
ritorni un oggetto del tipo dichiarato dal metodo stesso.
String args [ ] – E’ la dichiarazione di un array di String. Contiene gli argomenti presenti nella riga di
comando seguiti dal nome della classe.
Per esempio:
java HelloWorldApp args[0] args[1] … … …
System.out.println(“Hello World!”);
Questa istruzione illustra l’uso del nome di una classe, del nome di un oggetto e della chiamata di un metodo.
Stampa la stringa “Hello World!” sullo standard output usando il metodo println() dell’oggetto out di tipo
PrintStream, referenziato dalla proprietà out della classe System.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
9
Modulo 1
Compilare ed eseguire HelloWorldApp
Compilazione:
Una volta creato il file sorgente HelloWorldApp.java, compilarlo con il seguente comando:
C:\java\sources>javac HelloWorldApp.java
Se il compilatore non restiruisce nessun messaggio, un nuovo file HelloWorldApp.class
viene creato nella stessa directory del file sorgente, se non altrimenti specificato.
Esecuzione:
Per eseguire l’applicazione HelloWorldApp, usare l’interprete Java interpreter, java, posto
nella directory bin.
C:\java\sources>java HelloWorldApp
Hello World!
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
10
Modulo 2
Modulo 2: Programmazione Orientata agli Oggetti
Questo modulo dà una descrizione dei termini classe, oggetto,
attributo, metodo e costruttore, spiega come scrivere il codice per
definire un metodo, accedere alle variabili membro di un oggetto
usando la “notazione punto” (dot notation), scrivere il codice per
creare ed inizializzare un oggetto.
Viene altresì spiegato l’uso della parola riservata “this” per accedere
all’oggetto “corrente” ed è introdotto l’uso dei modificatori private e
public.
Si apprenderà l’uso delle asserzioni di package ed import per accedere
alle librerie e l’uso della documentazione online delle Java Application
Programming Interface (API).
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
11
Modulo 2
Che cosa è un oggetto (object)?
Definizione: Un oggetto (object) è un insieme software di variabili e relativi metodi.
Gli Object sono fondamentali per la comprensione della tecnologia object-oriented. Ci si può guardare intorno ed accorgersi
di quanti oggetti esistono nel mondo reale che possiamo prendere come esempio: un cane, una scrivania, una tv, una
bicicletta.
Tutti questi oggetti nel mondo reale condividono due caratteristiche: Essi possiedono uno stato ed un comportamento.
Per esempio, i cani hanno uno stato (nome, colore, razza, l’essere affamato) ed un comportamento (abbaiare, cercare,
dimenare la coda). Una bicicletta ha uno stato (la marcia corrente, il ritmo della pedalata, due ruote, il numero delle marce) ed
un comportamento (frenare, accelerare, rallentare, cambiare la marcia).
Gli object software sono modellizzati in modo tale da riflettere in essi le caratteristiche che posseggono nel mondo reale in
termini di stato e comportamento.
• Un object mantiene il suo stato in una o più variabili.
• Una variabile è un singolo dato riferito da un identificatore (nome della variabile).
• Un object implementa i suoi comportamenti per mezzo dei metodi.
• Un metodo è una funzione (subroutine) associata ad un object.
Rappresentazione di
un object:
Metodi
(comportamenti)
Ignazio Testoni
Variabili
(stato)
Rappresentazione di
una bicicletta
modellizzata in un
object:
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
12
Modulo 2
Che cosa è una Classe (class)?
Definizione: Una classe è il modello, o prototipo, che definisce le variabili e i metodi comuni a tutti
gli oggetti di un certo tipo.
Nel mondo reale certamente esistono diversi oggetti dello stesso tipo. Per esempio la nostra bicicletta è solo una
delle tante che esistono nel mondo. Usando una terminologia object-oriented, si potrebbe dire che il nostro object
bicicletta è una istanza della classe di oggetti noti come biciclette. Tutte le biciclette posseggono un certo stato (una
marcia innestata, un certo ritmo di pedalata, due ruote) ed un certo comportamento (cambiare marcia, frenare) in
comune. Ma certamente, lo stato di ciascuna bicicletta è indipendente e può essere diverso da quello di tutte le altre
biciclette.
Coloro che producono le biciclette si avvantaggiano del fatto che tutte le biciclette abbiano certe caratteristiche in
comune, costruendo diverse biciclette per mezzo dello stesso modello. Sarebbe infatti estremamente inefficiente
produrre un nuovo modello per ciascuna bicicletta da produrre.
Nel software object-oriented è possibile allo stesso modo avere molti oggetti dello stesso tipo che condividano le
stesse caratteristiche: rettangoli, schede per indirizzi, video clip, e così via. Proprio come per i produttori di
biciclette, si può trarre vantaggio dal fatto che gli oggetti dello stesso tipo sono simili ed è possibile creare un
modello per questi oggetti. Un modello software di un oggetto è chiamato classe.
Rappresentazione della
classe Bicicletta:
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
13
Modulo 2
Metodi speciali: i Costruttori
Ogni oggetto può essere inizializzato in maniera diversa.
Per esempio si può inizializzare un oggetto bicicletta di colore rosso e con 5 marce.
Ma dovrebbe essere possibile inizializzare una bicicletta generica con un colore ed un numero di marce predefiniti.
Si può inizializzare un oggetto chiamando un metodo speciale, il costruttore.
Ogni oggetto può avere uno o più costruttori.
I Costruttori sono definiti con le due regole seguenti:
 Il loro nome deve combaciare esattamente con il nome della classe.
 Essi non devono avere dichiarazione di tipo e non devo ritornare nulla al contrario dei normali metodi.
public class Bicycle{
public Bicycle(){ // Costruttore senza argomenti (default constructor)
// inizializza l’oggetto.
}
public Bicycle(int x, String color){ // Costruttore con argomenti
// int, String – argomenti del costruttore
// inizializza l’oggetto usando i parametri int x e String color.
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
14
Accedere ai metodi ed alle proprietà
Modulo 2
Si può accedere ai metodi ed alle proprietà di un oggetto per mezzo della “dot notation”.
package corso;
// Bicycle.java
import java.util.*;
public class Bicycle{
int nGear;
String color;
public Bicycle(int g, String col){
this.setColor(col);
}
public void setColor(String col){
this.color=col;
}
public String getColor(){
return this.color;
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
15
Usare la documentazione online Java API
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
Modulo 2
29 giugno – 7 luglio 2007
16
Modulo 3
Modulo 3: identificatori, parole riservate, tipi
Il linguaggio di programmazione Java contiene molti costrutti simili a quelli del linguaggio C.
Questo modulo dà una panoramica generale dei costrutti disponibili e della sintassi generale
richiesta da ciascun costrutto. Viene altresì introdotto un approccio di base object-oriented
alla associazione di dati usando tipi di dati aggregati.
 Commenti: Si possono usare tre diversi stili di commenti:
// commenti su una linea
/* commenti su una o più linee */
/** commenti per la documentazione delle classi (JavaDoc) */
 Punto e virgola, Blocchi, e Spazi: In Java, una asserzione è una singola linea di codice
terminata da un punto e virgola(;).
Per esempio: totale = a + b + c + d + e + f;
Un blocco è un insieme di istruzioni racchiuso da parentesi graffe ({}).
I blocchi di istruzioni sono anche usati per raggruppare le linee di codice appartenenti ad una
classe.
 Gli spazi (whitespace) sono usati per separare i vari elementi del codice sorgente. E’
consentito un numero arbitrario di whitespace. Per whitespace si intendono gli spazi, tab, e
ritorno a capo. E’ buona norma utilizzarli anche per rendere il codice sorgente più leggibile.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
17
Modulo 3
Identificatori
In Java, un identificatore è un nome dato ad una variabile, una classe o un metodo. Gli identificatori
iniziano con una lettera, underscore (_) o il simbolo del dollaro($). I caratteri successivi possono essere
numeri.
Gli identificatori sono case sensitive e non hanno una lunghezza massima.
Quelli che seguono sono identificatori validi:
 identifier
 userName
 User_name
 _sys_var1
 $change
Un identificatore non può essere una parola riservata ma può contenerla come parte del suo nome.
Per esempio, thisOne è un identificatore valido, ma this non lo è essendo this una parola riservata.
Notazione Java per gli identificatori:
Nomi delle classi: iniziano con lettera maiuscola, per esempio “MotorCycle”.
Nomi delle variabili e dei metodi: iniziano con una lettera minuscola, per esempio: “gearsNumber”
(variabile), “getGearsNumber()” (metodo).
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
18
Modulo 3
Tabella delle parole riservate
abstract
do
implements
private
throw
boolean
double
import
protected
throws
break
else
instanceof
public
transient
byte
extends
int
return
true
case
false
interface
short
try
catch
final
long
static
void
char
finally
native
super
volatile
class
float
new
switch
while
continue
for
null
synchronized
default
if
package
this
Le parole in ROSSO sono i tipi di dato base in Java
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
19
Modulo 3
Tipi di dato Base in Java
Il linguaggio Java definisce otto tipi di dato primitivi ed un tipo speciale.
I tipi di dato primitivi si possono considerare in quattro categorie:
 Logico
boolean
 Testuale
char
 Intero
byte, short, int, long
 Virgola mobile
double, float
I valori di tipo logico hanno solo due stati: true
o false.
Un valore di questo tipo è rappresentato dal
tipo boolean.
Esempio:
// dichiarare la variabile truth come boolean
// ed assegnarle il valore true
boolean truth = true;
Ignazio Testoni
Caratteri singoli sono rappresentati usando il tipo char.
Un char rappresenta un carattere unsigned Unicode a
16 bit. E’ necessario racchiudere un letterale char con
le virgolette singole (‘’).
• ‘a’
La lettera a.
• ‘\t’
Un tab.
• ‘\u????’ Uno specifico carattere Unicode dove ????
rappresentano 4 cifre esadecimali.
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
20
Modulo 3
byte, short, int, long
La lunghezza in bit e l’intervallo dei valori per i quattro tipi di dato interi sono mostrati
nella tabella seguente.
La rappresentazione dell’intervallo dei valori è definita dalle specifiche Java come
complemento a due ed è indipendente dal sistema (platform independent).
Lunghezza
Nome o Tipo
Intervallo valori
8 bit
byte
da -27 a 27-1
16 bit
short
da -215 a 215-1
32 bit
int
da -231 a 231-1
64 bit
long
da -263 a 263-1
float e double
Il formato di un numero in virgola mobile è definito usando le lunghezze mostrate in
tabella ed è indipendente dal sistema usato.
Ignazio Testoni
Lunghezza
Nome o Tipo
32 bit
float
64 bit
double
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
21
Modulo 3
Comprendere gli Oggetti
I primi linguaggi di programmazione e tipicamente i programmatori alle prime armi tendono a
trattare variabili individuali come entità isolate. Per esempio, se un programma deve manipolare una
data, normalmente sarebbero necessari tre interi separati.
int day, month, year;
Questa istruzione fa due cose. Indica che, quando il programma si riferisce ad un giorno, mese o
anno, sta trattando un tipo di dato intero. Essa alloca anche lo spazio necessario per questi interi.
Benché questo approccio sia semplice da comprendere, ha due lacune significative. Per prima cosa,
se il programma necessita di tracciare diverse date allora sono necessarie altre tre dichiarazioni per
ciascuna data:
int myBirthDay, myBirthMonth, myBirthYear;
int yourBirthDay, yourBirthMonth, yourBirthYear;
Questo metodo si rende velocemente noioso a causa del numero di variabili via via richieste.
La sua seconda lacuna è che lo schema ignora l’associazione fra giorno, mese ed anno e tratta i tre
valori in maniera indipendente. Ciascuna variabile è parte di una singola unità (in questo caso una
data) e dovrebbe essere opportunamente considerata.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
22
Modulo 3
Creare un nuovo tipo
Per superare queste due lacune il Java usa la classe (class) per creare nuovi tipi.
Per esempio, per definire un tipo che rappresenti una data è necessario allocare spazio sufficiente
per tre interi. Inoltre a questi tre interi deve essere attribuito il significato di giorno, mese ed anno:
class MyDate{
int day;
int month;
int year;
}
La parola class è riservata e deve essere scritta in caratteri minuscoli. Il nome MyDate è scritto così
per convenzione piuttosto che per necessità sintattiche.
Si può dichiarare una variabile del tipo MyDate e le parti day, month, and year sono già implicite
nella stessa dichiarazione:
MyDate myBirth, yourBirth;
Usando questa dichiarazione il Java rende disponibile l’accesso alle variabili (day, month, year),
dette membri, usando l’operatore punto (.):
myBirth.day = 26;
myBirth.month = 11;
yourBirth.year = 1960;
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
23
Modulo 3
Creare un oggetto
Quando vengono dichiarate variabili di uno dei tipi primitivi (boolean, byte, short, int,…), lo spazio
in memoria è allocato immediatamente in maniera automatica all’atto della dichiarazione stessa. La
dichiarazione di una variabile, usando tipi non primitivi come String o Date, invece non alloca lo
spazio necessario all’oggetto.
Infatti, una variabile dichiarata di un tipo di classe non rappresenta il dato in se stesso ma
rappresenta piuttosto un riferimento o puntatore ai dati.
Ma prima di poter usare la variabile bisogna allocare la memoria necessaria.
Per far questo si usa la parola riservata new nel modo che segue:
MyDate myBirth;
myBirth = new MyDate();
La prima istruzione, la dichiarazione, alloca solo lo spazio necessario per il puntatore. La seconda
alloca lo spazio, chiamato oggetto, per i tre interi usati per formare MyDate. Gli assegnamenti
relativi all’oggetto inizializzano la variabile myBirth affinché si riferisca correttamente al nuovo
oggetto. Dopo che queste due operazioni sono state effettuate, il contenuto dell’oggetto MyDate è
reso disponibile attraverso myBirth.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
24
Modulo 4
Modulo 4: Espressioni e controllo di flusso
Questo modulo illustra le espressioni, incluso gli operatori e la sintassi del Java.
Variabili e scope (ambito di validità).
• Le variabili definite nell’ambito di un metodo sono dette variabili locali, talvolta riferite anche
come automatiche, temporanee, o di stack.
• Le variabili definite all’esterno di un metodo sono create allorché l’oggetto è costruito usando
la chiamata new Xyz(). Esistono due tipi possibili di variabili.
Il primo tipo è la variabile di classe che è dichiarata usando la parola riservata static. Essa
viene creata nel momento in cui la classe è caricata. Le variabili di classe persistono in
memoria fino a che la classe non viene scaricata.
Il secondo tipo è una variabile di istanza (instance variable), dichiarata senza la parola
riservata static. Le variabili di istanza continuano ad esistere finché l’oggetto risulta
referenziato. Talvolta questo tipo di variabili sono dette variabili membro in quanto sono
membri di una classe. La parola riservata static sarà discussa in seguito più dettagliatamente.
• Le variabili parametro in un metodo definiscono gli argomenti passati in una chiamata ad un
metodo. Ogni qualvolta un metodo viene invocato, una nuova variabile viene creata e termina
solo quando il metodo ha terminato la sua esecuzione.
Esempio: OurClass.java
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
25
Modulo 4
Inizializzazione delle variabili
Nessuna variabile in Java si può usare se prima non viene inizializzata.
Quando un oggetto viene creato, le variabili di istanza vengono inizializzate con i seguenti valori
nel momento in cui la memoria viene allocata.
byte
0
short
0
int
0
long
0L
float
0.0F
double
0.0D
char
‘\u0000’ (NULL)
boolean
false
All reference type
null
Nota – I caratteri L, F, D sono
facoltativi e servono sono a
ricordare il tipo di variabile.
Nota – Un puntatore che ha valore
null non si riferisce a nessun
oggetto. Ogni tentativo di usare
l’oggetto causa una eccezione
(exception). Le eccezioni sono
errori che accadono a runtime e
verranno discusse in seguito.
Mentre le variabili definite all’esterno di un metodo sono inizializzate automaticamente, le
variabili locali devono essere inizializzate manualmente prima del loro uso. Il compilatore riporta
un errore se determina una condizione dove una variabile potrebbe essere usata prima di essere
inizializzata. (Inizializzazione.java)
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
26
Modulo 4
Espressioni - Operatori
Gli operatori in Java sono simili, per stile e funzione, a quelli del C o C++. La seguente tabella
elenca gli operatori in ordine di precedenza (da L a R significa da sinistra a destra)
Separatore
. [] () ; ,
da R a L
++ -- + - ~ ! (data type)
da L a R
* / %
da L a R
+ -
da L a R
<< >> >>>
da L a R
< > <= >= instanceof
da L a R
== !=
da L a R
&
da L a R
^
da L a R
|
da L a R
&&
da L a R
||
da R a L
?:
da R a L
= *= /= %= += -+ <<=
>>= >>>= &= ^= |=
Ignazio Testoni
Gli operatori && (AND) e || (OR) valutano
espressioni logiche di tipo short-circuit:
MyDate d = null;
if ((d != null) && (d.day > 32)){
// do something with d
}
L’espressione di tipo boolean che forma l’argomento
dell’istruzione if() è lecita e completamente sicura.
Lo è perché la seconda sub-espressione viene
ignorata quando la prima sub-espressione è falsa,
essendo l’intera espressione sempre falsa quando è
falsa la prima, non importa quale sia il valore della
seconda.
Nota - instanceof è una parola riservata solo in Java.
Gli altri operatori possono essere comuni anche in
altri linguaggi.
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
27
Modulo 4
Espressioni - Operatori
Concatenazione di stringhe (String) con +
L’operatore + effettua la concatenazione di oggetti di tipo String, producendo un
nuovo oggetto String.
String salutation = “Dr. ”;
String name = “Pete ” + “Seymour.”;
String title = salutation + name;
Il risultato dell’ultima riga è:
Dr. Pete Seymour.
Se uno dei due argomenti dell’operatore + è un oggetto String, allora l’altro viene
automaticamente convertito in String. Ogni object può essere convertito
automaticamente in String, benché il risultato a volte può risultare apparentemente
senza senso. Un oggetto che non è di tipo String viene convertito in una stringa
equivalente per mezzo del metodo toString().
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
28
Modulo 4
Espressioni - Casting
Il casting consiste nell’assegnazione di un tipo ad una variabile di un altro tipo. Se i due
tipi sono compatibili, il Java effettua la conversione automaticamente. Per esempio, un
valore di tipo int può sempre essere assegnato ad una variabile di tipo long.
Qualora il casting comporti perdita di informazione, il compilatore richiede che si
confermi l’assegnazione con un ‘typecast’. Questo per esempio si può fare forzando un
valore di tipo long in una variabile di tipo int. Il casting esplicito ha la sintassi seguente:
long bigValue = 99;
int squashed = (int)(bigValue);
Il tipo di variabile in cui si vuole fare il casting è posto fra parentesi ed usato come
prefisso all’espressione da modificare. Benché non sempre necessario, è consigliabile
racchiudere l’intera espressione tra parentesi. In questo modo il codice risulta più
leggibile mentre viceversa, la precedenza fra le operazioni di casting potrebbe creare
problemi.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
29
Promozione e Casting di Espressioni
Modulo 4
Le variabili possono essere promosse ad una forma più lunga (in termini di bit), se non vi è
perdita di informazione.
long bigValue = 6;
// 6 è un tipo int, OK
int smallValue = 99L;
// 99L è un long, illegale
double z = 12.414F;
// 12.414 è un float, OK
float z1 = 12.414;
// 12.414 è un double, illegale
In generale si può dire che una espressione è compatibile in assegnamento se il tipo di
variabile è lunga (in termini di bit) almeno quanto il tipo dell’espressione.
Per l’operatore +, quando i due operandi sono tipi numerici primitivi, il risultato è almeno un
int ed ha un valore calcolato promuovendo il risultato al tipo più grande fra i due operandi.
Questo potrebbe però causare un overflow o una perdita di precisione.
Per esempio il frammento di codice seguente
short a, b, c;
a = 1;
b = 2;
c = a + b;
causa un errore perché esso promuove ciascun short ad un int prima di operare su di loro.
Invece se c fosse dichiarato come int o se venisse fatto un typecast del tipo:
c = (short)(a+b);
Il codice funzionerebbe.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
30
Costrutti condizionali - if
Modulo 4
Istruzioni if, else
La sintassi fondamentale per le istruzioni if, else è:
if ( boolean expression ){
istruzione o blocco di istruzioni;
}else{
istruzione o blocco di istruzioni;
}
Opzionalmente si possono aggiungere più condizioni alternative:
if ( boolean expression1 ){
istruzione o blocco di istruzioni;
}else if ( boolean expression2 ){
istruzione o blocco di istruzioni;
}else if ( boolean expression3 ){
istruzione o blocco di istruzioni;
}else{
istruzione o blocco di istruzioni;
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
31
Modulo 4
Costrutti condizionali - switch
Istruzione switch
Esempio 1:
La sintassi per l’istruzione switch è:
switch (expression1 ){
case constant2:
statements;
break;
case constant3:
statements;
break;
default:
statements;
break;
}
L’etichetta opzionale default è usata solo per
specificare il segmento di codice da eseguire
quando il valore della variabile o l’espressione
valutata da switch non corrisponde a nessuno dei
valori specificati nei vari valori case.
Se non c’è l’istruzione break come ultima
istruzione del segmento di codice relativo a
ciascun case l’esecuzione continua nel segmento
di codice del case successivo senza verificare il
valore del relativo case.
Ignazio Testoni
int colorNum = 0;
switch (colorNum ){
case 0:
setBackground(Color.red);
break;
case 1:
setBackground(Color.green);
break;
default:
setBackground(Color.black);
break;
}
Esempio 2:
switch (colorNum ){
case 0:
setBackground(Color.red);
case 1:
setBackground(Color.green);
default:
setBackground(Color.black);
break;
}
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
32
Modulo 4
Costrutti ciclo (loop) - for()
I costrutti del tipo ciclo consentono di ripetere l’esecuzione di un certo blocco di istruzioni. Il
Java supporta tre tipi di questi costrutti: i cicli for, while e do.
Ciclo for
La sintassi per il ciclo for è:
for(init_expr [, init_expr2, init_expr3…] ; boolean
test_expr; alter_expr){
istruzione o blocco di istruzioni;
}
Esempio:
for ( int i = 0; i < 10; i++ ){
System.out.println(“Are you finished yet ?”);
}
System.out.println(“Finally !”);
Nota – E’ consentito usare la virgola all’interno del ciclo for(). Per esempio,
for ( i = 0, j = 0; j < 10; i++, j++) {} è lecito.
Nel precedente esempio, int i è dichiarato e definito contestualmente all’interno del blocco
for. La variabile i è accessibile solo all’interno del blocco di questo ciclo for;
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
33
Modulo 4
Costrutti ciclo (loop) - while()
Ciclo while
La sintassi del ciclo while è:
while (bolean test_expr) {
istruzione o blocco di istruzioni;
}
Esempio:
int i = 0;
while ( i < 10 ){
System.out.println(“Are you finished yet ?”);
i++;
}
System.out.println(“Done !”);
Accertarsi sempre che la variabile di controllo sia opportunamente inizializzata
prima che il blocco del ciclo inizi la sua esecuzione ed accertarsi che la condizione
sia true perché esso possa iniziare. E’ necessario sempre aggiornare la variabile in
maniera adeguata per prevenire la condizione di ciclo infinito.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
34
Modulo 4
Costrutti ciclo (loop) - do()
Ciclo do
La sintassi del ciclo do è:
do {
istruzione o blocco di istruzioni;
} while (boolean test);
Esempio:
int i = 0;
do {
System.out.println(“Are you finished yet ?”);
i++;
}while ( i < 0);
System.out.println(“Done !”);
Proprio come i cicli while, acertarsi che la variabile di controllo del ciclo sia
opportunamente inizializzata, aggiornata all’interno del ciclo ed appropriatamente
controllata.
• Usare il ciclo for nei casi in cui il ciclo debba essere eseguito un numero
predeterminato di volte.
• Usare i cicli while e do nei casi in cui non è possibile predeterminare il numero dei
cicli da eseguire.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
35
Modulo 5
Modulo 5: Array
In questo modulo si descrive come sono dichiarati, creati, inizializzati e copiati gli array in Java
Dichiarazione di un array:
Gli array sono usati tipicamente per raggruppare oggetti dello stesso tipo. Gli array consentono di
riferirsi al gruppo di oggetti per mezzo di un unico nome.
Si possono dichiarare array di qualsiasi tipo, sia primitivo, sia di classe:
char s[];
Point p[]; // dove Point è una classe.
In Java, un array è un aggetto anche se l’array è composto da tipi primitivi e, come gli altri tipi di
classe, la dichiarazione non crea automaticamente l’oggetto stesso. Piuttosto, la dichiarazione di un
array crea un puntatore (reference) che si deve usare per indirizzare l’array. La memoria necessaria
usata dagli elementi dell’array è allocata dinamicamente o tramite l’istruzione new o tramite un
inizializzatore di array.
Il Java permette una forma alternativa con le parentesi quadre a sinistra:
char [] s;
Point [] p; // dove Point è una classe.
Entrambi i formati sono usati e la dichiarazione non specifica la dimensione dell’array.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
36
Modulo 5
Creazione di un array
Gli array si possono creare come tutti gli altri oggetti, usando l’istruzione new:
s = new char[20];
p = new Point[100];
Il primo crea un array di 20 elementi di tipo char (primitivo).
Il secondo crea un array di 100 elementi di tipo Point (oggetto).
Ma non crea 100 oggetti di tipo Point. Questi debbono essere creati separatamente:
p[0] = new Point();
p[1] = new Point();
... oppure
for(int c = 0; c < 100; c++){
p[c] = new Point();
}
L’indice usato per indirizzare i singoli elementi di un array inizia sempre da zero e deve rimanere
sempre in un intervallo compreso fra zero ed un valore comunque minore della lunghezza dell’array.
Qualsiasi tentativo di accedere ad un elemento dell’array non compreso in questo intervallo (0 -> N-1)
crea un errore a runtime.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
37
Modulo 5
Inizializzazione di un array
Quando si crea un array, ciascun elemento viene inizializzato. Nel caso dell’array di char s, nella
sezione precedente, ciascun valore è inizializzato a zero ('\u0000' – carattere null). Nel caso dell’array
p ciascun valore è inizializzato a null, indicando cioè che ancora non ci si riferisce ad un oggetto di
tipo Point. Dopo che l’assegnazione p[0] = new Point() è stata fatta, il primo elemento dell’array si
riferisce ad un oggetto Point reale, allocandone così la relativa memoria.
Nota – Inizializzare tutte le variabili, incluso gli elementi degli array, è essenziale per la sicurezza del
sistema. Non si deve mai fare uso di variabili senza prima inizializzarle.
Il Java consente una forma abbreviata per creare array e nello stesso tempo inizializzarne i valori:
String names [] = {
"Paul",
"George",
"Linda"
};
Bycicle [] cycles = {
new Bycicle(Color.red),
new Bycicle(Color.black),
new Bycicle(Color.grey)
};
Ignazio Testoni
Inizializzatore di array
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
38
Modulo 5
Array multidimensionali
In Java gli array multidimensionali si usano diversamente dagli altri linguaggi. Poiché è consentita la
creazione di array di qualunque tipo, essendo un array a sua volta un oggetto, si possono creare array
di array (e array di array di array) e così via. L’esempio seguente mostra un array bidimensionale:
int twoDim [] [] = new int [4] [];
twoDim[0] = new int[5];
twoDim[1] = new int[5];
L’oggetto creato dalla prima chiamata new è un array che contiene quattro elementi. Ciascun elemento
deve essere inizializzato separatamente cosicché ciascun elemento punti al suo array.
Poiché gli elementi si inizializzano separatamente, è possibile creare array di array non rettangolari.
Cioè, gli elementi di twoDim si possono così inizializzare:
twoDim[0]
twoDim[1]
twoDim[2]
twoDim[3]
=
=
=
=
new
new
new
new
int
int
int
int
[2];
[4];
[6];
[8];
Questo tipo di inizializzazione risulta piuttosto noiosa, e poiché la forma più comune di array
bidimensionale è di tipo rettangolare, esiste una forma abbreviata per creare array bidimensionali.
L’esempio mostra la creazione di un array di quattro array di cinque interi ciascuno.
int twoDim [] [] = new int [4] [5];
Il numero degli elementi in un array è memorizzato come parte dell’oggetto array stesso nella
proprietà o attributo length.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
39
Modulo 6: Struttura delle classi
Modulo 6
Questo modulo porta l’introduzione ai concetti degli oggetti in Java descritti nel modulo 2 ad un livello
successivo, considerando i concetti di overloading, overriding, subclassing, ed un approfondimento sui
costruttori.
La programmazione orientata agli oggetti (OOP) consente di modellizzare concetti del mondo reale
all’interno di un programma per computer. In essa si possono trovare le caratteristiche della programmazione
strutturata ed un meccanismo per organizzare dati ed algoritmi. I concetti fondamentali dei linguaggi OOP
sono tre:
Incapsulamento, polimorfismo, ed ereditarietà. Tutti e tre sono indissolubilmente legati al concetto di
classe.
Definizione dei metodi:
Il Java utilizza un approccio simile ad altri linguaggi, particolarmente C and C++, per definire i metodi. Le
dichiarazioni hanno la forma seguente:
< modificatore > < tipo di oggetto > < nome > ( [< lista argomenti >] ) [throws < exception >] { ... }
• < nome >: può essere qualunque identificatore lecito.
• < tipo di oggetto >: tipo di valore restituito dal metodo.
• < modificatore >: public, private, protected, static...
• < lista argomenti >: argomenti passati al metodo.
• throws < exception >: riporta un eventuale specifico errore all’atto della chiamata del metodo.
Per Esempio,
public void addDays( int days ){
< block > // Blocco di istruzioni …
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
40
Modulo 6
Passaggio per valore
Il Java passa gli argomenti esclusivamente “per valore”; cioè, l’argomento non può essere cambiato
dalla chiamata al metodo.
Quando l’istanza di un oggetto è passata come argomento ad un metodo, il valore dell’argomento
è il riferimento all’oggetto.
Il contenuto dell’oggetto può essere cambiato nel metodo chiamato, ma il riferimento all’oggetto
invece non può mai essere cambiato.
Car ferrari = new Car();
ferrari.setSpeed(65);
changeParameters(ferrari);
System.out.println(“The speed = “+ferrari.getSpeed());
public void changeParameters(Car c){
//changes the car’s speed outside this method!
c.setSpeed(200.0);
}
Il risultato stampato dipende da cosa succede all’interno del metodo changeParameters():
“The speed = 200”
PerValore.java
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
41
Modulo 6
Incapsulamento
Con l’uso della parola riservata private, nella dichiarazione di day, month, year nell’oggetto MyDate,
si rende impossibile l’accesso a queste varabili membro da parte di qualunque blocco di codice a meno
che il codice che tenti di accedere ai membri private appartenga alla classe stessa.
Prevenire l’accesso diretto alle variabili potrebbe sembrare strano, ma consente enormi vantaggi per la
qualità del programma che usa la classe MyDate. Poiché i singoli elementi di dato sono inaccessibili,
l’unico modo che c’è per leggerli o modificarli è attraverso i metodi. Se un programma richiede la
consistenza interna dei membri della classe è possibile ottenerla per mezzo dei metodi della classe
stessa.
MyDate d = new MyDate(2003, 2, 28);
d.day = 31; // giorno inesistente !!!
d.month = 19; // mese inesistente !!!
Si può verificare la consistenza del dato mese con un metodo appropriato:
public void setMonth(int m){
if (m < 13 && m > 0){
this.month = m;
}else{
System.out.println(“Il mese ”+m+” non è
un numero di mese valido !”);
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
42
Overload dei nomi dei metodi
Modulo 6
In certe circostanze potrebbe risultare comodo scrivere diversi metodi nella stessa classe che
fondamentalmente facciano la stessa cosa ma con argomenti diversi.
Per esempio il metodo println():
public
public
public
public
void
void
void
void
println(int i)
println(float f)
println(String s)
println()
La lista degli argomenti deve essere diversa.
Il tipo restituito potrebbe essere diverso.
Java permette di riutilizzare un nome per più di un metodo.
I nomi dei metodi si possono riutilizzare a condizione che le signature (numero e tipo degli
argomenti) dei metodi siano tutte diverse. Se così non fosse si verrebbero a creare delle ambiguità che
ovviamente non sono ammesse. Nel caso dei tre metodi println le signature sono diverse essendo
sempre diversi gli argomenti con cui sono dichiarate.
Il Java allora sceglie il metodo da eseguire in base al tipo di argomenti con cui viene chiamato il
metodo.
La lista degli argomenti nella dichiarazione di un metodo è detta appunto method signature.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
I costruttori
43
Modulo 6
L’istruzione:
MyDate birthDate = new MyDate();
dichiara ed effettua l’inizializzazione del nuovo oggetto birthDate, istanza della class MyDate.
La fase finale dell’inizializzazione di un nuovo oggetto è quella di eseguire un metodo chiamato
costruttore.
I costruttori sono identificati da due regole:
• Il nome del metodo deve essere esattamente identico al nome della classe.
• Esso non deve ritornare nessun tipo di dato nella dichiarazione.
Esattamente come un normale metodo, è possibile effettuare l’overload del costruttore con altri
costruttori ovviamente con diverse signature. Quando si esegue una chiamata new
Xyz(lista_argomenti), la signature determina quale costruttore debba essere usato.
public class Bicycle{
private int gears=5;
private String color="black";
private String name="no name";
public Bicycle(){ // costruttore predefinito
}
public Bicycle(int gears, String color){ // int, String
// costruttore
this.gears = gears;
this.color=color;
}
public Bicycle(int gears, String color, String name){
this(gears, color);
this.name = name;
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
– args
29 giugno – 7 luglio 2007
44
Ereditarietà (subclassing)
Modulo 6
I linguaggi OOP possiedono uno speciale meccanismo che consente al programmatore di definire una
classe partendo da una classe già definita in precedenza. A tale scopo si usa la parola riservata extends:
public class Employee {
String name;
String hireDate;
Date dateOfBirth;
String jobTitle;
int grade;
...
}
public class Manager extends
Employee {
String department;
Employee subordinates [];
...
}
Ignazio Testoni
In questo caso la classe Manager è definita in modo
tale da avere tutti i metodi e tutte le proprietà che ha
la classe Employee. Tutti i metodi e tutte le proprietà
sono ereditate dalla definizione della classe genitore.
Tutto quello che il programmatore deve fare è di
definire le caratteristiche in più o specificare quali
cambiamenti apportare (alla classe Employee).
Questo
approccio
rappresenta
un
grande
miglioramento in termini di manutenibilità ed
affidabilità del codice. Se viene apportata una
correzione alla classe Employee, allora anche la
classe Manager sarà corretta automaticamente senza
che il programmatore debba fare nulla ad eccezione
di una ricompilazione. E’ consentito estendere solo
una classe.
Il Java infatti supporta solo la singola ereditarietà.
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
45
Modulo 6
Ereditarietà singola
Employee
attributi
name
address
salary
Engineer
Due modi per includere un costruttore sono:
• Usare il costruttore di default
• Scrivere uno o più costruttori espliciti
Secretary
Manager extends Employee
metodi
upSalary
attributi
bonus
metodi
upBonus
Director extends Manager
attributi
car allowance
metodi
upAllowance
• Una sottoclasse eredita tutti i metodi e
le variabili dalla superclasse
• La sottoclasse non eredita il costruttore
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
46
Modulo 6
Polimorfismo
Il polimorfismo è la capacità per un oggetto di avere forme differenti; per esempio la classe
Manager ha accesso ai metodi della classe Employee.
• Un oggetto ha solo una forma.
• Una variabile reference ha diverse forme; essa può riferirsi ad oggetti di forma diversa.
Una variabile è polimorfica in quanto può riferirsi ad oggetti dalle forme diverse. In Java c’è solo
una classe genitore di tutte le classi, la classe java.lang.Object.
La classe Object definisce una serie di metodi utili, incluso toString(), motivo per cui ogni
oggetto in Java può essere convertito in una rappresentazione di tipo String.
Java consente di riferirsi ad un oggetto tramite una variabile del tipo della classe genitore. Così è
possibile dire:
Employee e = new Manager();
Riferendosi però alla variabile e così com’è, si può accedere solo a quelle parti dell’oggetto che
sono parte di Employee; le parti specifiche relative a Manager non sono disponibili.
Employee
Ignazio Testoni
Manager
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
47
Modulo 6
Polimorfismo: un esempio
Si definisca una generica classe FiguraGeometrica che abbia i seguenti metodi:
 getArea()
 getPerimeter()
 getName()
// calcola il area
// calcola il perimetro
// leggi il nome
Si definiscano le seguenti classi che estendano FiguraGeometrica e che abbiano le loro
proprie implementazioni dei metodi suddetti:
 Cerchio
 Triangolo
 PoligonoRegolare
extends FiguraGeometrica
extends FiguraGeometrica
extends FiguraGeometrica
Si definisca la classe Calcola che dichiari un array di oggetti FiguraGeometrica.
L’array in questione deve contenere varie istanze di oggetti del tipo delle classi sopraelencate
e ne deve calcolare area e perimetro.
FiguraGeometrica.java
Cerchio.java
Triangolo.java
Calcola.java
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
48
Modulo 6
L’operatore instanceof
public class Employee extends Object
public class Manager extends Employee
public class Contractor extends Employee
Dato il fatto che è possibile referenziare un oggetto tramite una delle sue classi genitore, talvolta
si ha la necessità di sapere effettivamente a quale classe appartenga un determinato oggetto.
Per questo scopo si usa l’operatore instanceof.
Nota – Ricordarsi che, benché accettabile, extends Object è sempre ridondante.
public void method (Employee e) {
if (e instanceof Manager) {
// Richiedi benefit, stock options
// nonché il salario opportuno
} else if (e instanceof Contractor ) {
// Richiedi la tariffa oraria
} else {
// impiegato normale…
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
49
Modulo 6
Casting di oggetti
Se non si fa uso dell’operatore instanceof, si corre il rischio di fallire il casting.
Generalmente ogni tentativo di effettuare un cast ad un reference di un oggetto è
soggetto a diversi controlli:
 Effettuare un “up casting” attraverso la gerarchia delle classi è sempre
consentito. Infatti si fa tramite un normale assegnamento.
 Per effettuare il “down casting”, il compilatore deve verificare che il casting
sia possibile. Per esempio, ogni tentativo di effettuare un cast da Manager a
Contractor è assolutamente non consentito, poiché Contractor non è certamente
un Manager. La classe verso cui si voule fare il casting deve essere una
sottoclasse del reference dell’oggetto che deve effettuare il casting.
 Se al livello di compilazione il casting è consentito, allora l’oggetto sarà
verificato a runtime. Per esempio, succede che se il controllo di instanceof è
omesso dai sorgenti, e l’oggetto da promuovere di fatto non è un oggetto del
tipo voluto, durante il runtime verrà generata una eccezione.
Employee
Contractor
Ignazio Testoni
Manager
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
50
Overriding dei metodi (sovrascrittura)
Modulo 6
Se in una classe figlio viene definito un metodo che ha lo stesso nome, lo stesso return type e la
stessa signature di un metodo della classe padre, si dice allora che il nuovo metodo effettua l’override
di quello vecchio.
 Una sottoclasse può modificare i comportamenti ereditati dalla classe genitore.
 Una sottoclasse può creare un metodo con funzionalità diverse rispetto a quelle della classe
genitore ma con gli stessi:
• Nome
• Return type
• Lista degli argomenti
public class Employee {
String name;
int salary;
public String getDetails(){
return “Name: ” + name + “\n”
+“Salary: ” + salary;
}
}
Ignazio Testoni
public class Manager extends Employee {
String department;
public String getDetails(){
return “Name: ” + name + “\n” +
“Manager of ” +
department;
}
}
// Il metodo originario getDetails è
stato sovrascritto
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
51
Modulo 6
L’istruzione super
L’istruzione super si riferisce alle superclasse della classe in cui l’istruzione è usata.
Essa si usa per fare riferimento alle variabili membro o ai metodi della superclasse.
Invocare i costruttori della classe genitore:
Talvolta si definisce un costruttore che prende degli argomenti e si vuole usare questi
argomenti per controllare la costruzione della parte padre di un oggetto. Si può invocare
uno specifico costruttore della classe padre come parte della inizializzazione della classe
figlio invocando l’istruzione super dalla prima linea del costruttore figlio.
public class Employee {
String name;
public Employee (String n){
this.name = n;
}
}
public class Manager extends Employee {
String department;
public Manager (String n, String d){
super(n);
this.department = d;
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
52
Modulo 6
Raggruppare le classi
Packages:
Il Java prevede il meccanismo dei package per raggruppare classi correlate fra loro. E’
possibile indicare che le classi di un file sorgente appartengono ad un particolare package
usando l’istruzione package:
La dichiarazione del package se esiste,
deve trovarsi all’inizio del file
sorgente. E’ consentito dichiarare solo
un package all’interno di un sorgente e
questa dichiarazione ha validità in
tutte le parti del file sorgente.
I nomi dei package sono gerarchici e
sono separati da un punto.
I package sono salvati in una directory
ad albero che contiene un ramo che è
appunto il nome del package. Il file
Employee.class
dovrebbe
essere
presente all’nterno della directory:
path/abc/financeDept/
L’opzione –d specifica al compilatore
la radice della gerarchia del package
in cui i file .class sono salvati.
Ignazio Testoni
// Class Employee of the Finance
department
// for the ABC company.
package abc.financeDept;
public class Employee {
...
}
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
53
Modulo 6
Raggruppare le classi
L’istruzione import:
 Indica al compilatore dove cercare le classi da usare
 Precede tutte le dichiarazioni della classe
// La classe Manager appartiene al
package attuale.
// La classe Manager appartiene al
package attuale.
import abc.financeDept.*;
public class Manager extends Employee {
String department;
Employee subordinates [];
...
}
public class Manager extends
abc.financeDept.Employee {
String department;
Employee subordinates [];
...
}
Il nome del package fa parte del nome completo di una classe.
Ci si può riferire alla classe Employee con abc.financeDept.Employee, oppure si può usare
l’istruzione import e solamente il nome della classe Employee. Quando si usa una dichiarazione
package, non è necessario importare lo stesso package o tutti gli elementi del package. Il
package attuale, che sia implicito od esplicito, fa sempre parte dello spazio dei nomi attuale.
L’istruzione import specifica solo la classe cui si vuole accedere. Per avere accesso a tutte le
classi di uno stesso package, usare il simbolo “*”: import java.awt.*;
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
54
Modulo 7: caratteristiche avanzate delle classi
Modulo 7
Variabili di classe (static)



Sono condivise fra tutte le istanze della classe.
Possono essere etichettate sia public che private.
Se etichettate public possono essere lette dal di fuori della classe anche se la
classe non è stata istanziata.
In questo esempio, ad ogni oggetto creato viene
assegnato un unico numero seriale, partendo da 1.
La variabile contatore è condivisa fra tutte le
istanze, in modo che quando il costruttore di un
oggetto incrementa il contatore, l’oggetto successivamente creato riceve il valore incrementato. Una
variabile di tipo static è assimilabile alle variabili
globali per altri linguaggi.
Se un variabile static è di tipo public, è possibile
accedervi dall’esterno della classe. Per poterlo fare
non è necessario avere un’istanza della classe ma vi
si può accedere indirizzandola per mezzo del nome
della classe in cui è definita.
Ignazio Testoni
public class Count {
private int serialNumber;
private static int counter = 0;
public Count(){
counter ++;
serialNumber = counter;
}
}
public class StaticVar {
public static int number;
}
public class OtherClass {
public OtherClass(){
int x = StaticVar.number;
}
}
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
55
Modulo 7
Caratteristiche avanzate delle classi - static
Metodi statici (static)
 E’ possibile invocare un metodo di tipo static senza la necessità di dover istanziare la classe a
cui il metodo appartiene.
 Si può accedere ad un metodo static usando il nome della classe piuttosto che una sua istanza
Poiché si può invocare un metodo statico senza alcuna istanza della classe a cui appartiene, un metodo
statico non può accedere a nessuna variabile che non sia definita all’interno del metodo stesso o che
non sia statica a sua volta. Ogni tentativo di riferimento a variabili non static causa un errore di
compilazione.
public class Wrong {
int x;
public static void main(String [] args){
x = 9; // ERRORE IN COMPILAZIONE !!!
}
}
Circa i metodi statici:
• main() è static poiché deve essere eseguito prima che sia
eseguita ogni altra istanza.
• Quando main() inizia, nessun oggetto è ancora stato creato.
• Un metodo static non può essere sovrascritto (overriden) da
un metodo non static.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
56
Caratteristiche avanzate delle classi - final
Modulo 7
Parola riservata final
 Classi final
Se una classe è etichettata come final essa non può essere estesa.
Per esempio, la classe java.lang.String è una classe final. Questo per ragioni di sicurezza,
poiché essa assicura che se un metodo ha dei riferimenti ad un oggetto di tipo String, questo
sia certamente una istanza della classe String senza che alcuno ne abbia potuto modificare le
proprietà o i metodi.
 Metodi final
I metodi dichiarati come final non possono essere sovrascritti (overridden). Anche questo per
motivi di sicurezza. Un metodo dovrebbe essere reso final se esso ha una implementazione
che non deve essere cambiata e che è critica per la consistenza dell’oggetto in sé.
Tutti i metodi dichiarati static o private sono automaticamente final.
 Variabili final
Dichiarare una variabile final ha l’effetto di renderla costante. Ogni tentativo di modificare il
contenuto di una variabile final genera un errore in compilazione.
public final int MAX_ARRAY_SIZE = 25;
NOTA – Una variabile di tipo reference (istanza di classe) dichiarata come final non può
riferirsi ad alcun altro oggetto. E’ invece possibile modificarne lo stato essendo final solo il
suo reference.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
57
Caratteristiche avanzate delle classi - abstract
Modulo 7
Parola riservata abstract
 Classi astratte (abstract)
Una classe che dichiara l’esistenza di uno o più metodi ma non le loro implementazioni è
chiamata classe astratta. Talvolta si ha la necessità di creare una classe che rappresenti certe
caratteristiche fondamentali e dichiari certi metodi, ma non è possibile implementarli
all’interno della classe stessa. Essi debbono essere implementati in una sotto-classe. Una
classe astratta può certamente dichiarare ed implementare metodi normali, il cui
comportamento è noto. Allo stesso modo una classe astratta può dichiarare ed usare variabili
membro come tutte le altre classi. Le classi astratte non possono essere istanziate, ma si può
dichiarare una variabile il cui tipo sia una classe astratta e poi riferirla in seguito ad una
istanza di una classe concreta.
 Metodi astratti (abstract)
I metodi che sono dichiarati ma non implementati, all’interno di una classe astratta, devono
essere dichiarati abstract.
Le classi che estendono una classe astratta devono implementare tutti i metodi dichiarati
astratti nella classe genitore. Se non lo fanno devono essere dichiarate astratte.
public abstract class Drawing {
public abstract void drawDot(int x, int y); // NON IMPLEMENTATO
public void drawLine(int x1, int y1, int x2, int y2){
// disegna usando ripetutamente il metodo drawDot().
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
58
Caratteristiche avanzate delle classi - Interfacce
Modulo 7
 Una interfaccia è una variazione dell’idea di classe astratta.
 In una interfaccia tutti i metodi sono astratti.
 Si può simulare l’ereditarietà multipla implementando più interfacce.
Nessuno dei metodi dichiarati può avere istruzioni ed in una interfaccia si possono dichiarare solo
variabili di tipo static final.
Una interfaccia dà solo l’impressione di aggirare la regola della singola ereditarietà. Mentre una classe
estende solo una singola classe, essa può implementare tute le interfacce che servono.
Quando una classe implementa una particolare interfaccia, essa deve implementare tutti i metodi
dichiarati in quella interfaccia. In questo modo è possibile chiamare i metodi dell’interfaccia su
qualsiasi oggetto della classe che implementa quella interfaccia.
Le interfacce servono a:
 Dichiarare i metodi che una o più classi devono poi implementare.
 Dichiarare una interfaccia di programmazione (API) senza però che sia
nota la modalità di esecuzione dei suoi metodi (può essere utile nella
distribuzione di un package di classi ad altri sviluppatori).
 Associare somiglianze fra classi diverse senza che siano per forza messe in
relazione fra loro.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
59
Wrapper Classes (classi involucro)
Modulo 7
In Java gli unici tipi di dato che non sono considerati oggetto sono i tipi di dato primitivi. In quanto tali
però essi non dispongono né di metodi né di proprietà.
Allora Java fornisce alcune wrapper classes per manipolare i tipi di dato primitivi come se fossero
oggetti.
Le wrapper classes sono utili per convertire fra loro tipi di dati primitivi tramite i numerosi metodi
disponibili.
int x = Integer.valueOf(str).intValue();
Ignazio Testoni
Tipo primitivo
Wrapper Class
boolean
Boolean
byte
Byte
char
Character
short
Short
int
Integer
long
Long
float
Float
double
Double
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
60
Modulo 7
Collection Framework
 Una collection (o un container) è un singolo oggetto che rappresenta un
gruppo di altri oggetti che formano i suoi elementi.
 Classi di tipo collection sono Vector, Bits, BitSet, Stack, Hashtable,
LinkedList.
 Le Collection API comprendono interfacce che considerano gli oggetto come:
 Collection – Gruppo di oggetti senza ordine specifico;
 Set – Gruppo di oggetti senza duplicati;
 List – Gruppo di oggetti ordinati, la duplicazione è permessa.
Es: Vector() -> prevede metodi per lavorare con array dinamici di vari tipi di elementi.
Metodi:
1.
2.
3.
4.
5.
6.
7.
8.
public int size();
public boolean contains(Object obj);
public int indexOf(Object obj);
public synchronized Object elementAt(int index);
public synchronized void setElementAt(Object obj, int index);
public synchronized void removeElementAt(int index);
public synchronized void addElement(Object obj);
... ...
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
61
Modulo 7
Collection Framework
A partire dalla versione 5 del JDK sono stati aggiunti tre nuovi meccanismi inerenti il cosiddetto Collection
Framework.
 Generics – ulteriori controlli in fase di compilazione per le classi collections che eliminano la necessità
di effettuare il cast in fase di lettura degli elementi dalle collections.
 Ciclo for avanzato – elimina la necessità degli iteratori espliciti quando si itera attraverso gli elementi
di una collection.
 Autoboxing/unboxing – converte automaticamente i tipi primitivi (per esempio int) nella loro wrapper
class (Integer) nel momento in cui li si inserisce in una collection, e converte le istanze delle wrapper
class dei loro corrispondenti tipi primitivi quando li si estrae dalla collection.
Vector<Integer>vector = new Vector<Integer>(); // Generics
vector.add(new Integer(1));
vector.add(2);
// Autoboxing
vector.add(3);
vector.add(3);
Iterator i = vector.iterator();
for(int j=0; j<vector.size();j++){
Integer n = vector.elementAt(j); // Casting non necessario
System.out.println(n);
// Unboxing
}
for(Integer n:vector) {
// Ciclo for avanzato
System.out.println(n);
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
62
Modulo 8: Eccezioni (Exceptions)
Modulo 8
Introduzione:
In Java la classe Exception definisce semplici condizioni di errore che i programmi potrebbero
incontrare. Piuttosto che lasciare il programma terminare, si può fare in modo di gestire le
eccezioni e continuare l’esecuzione del programma.
Per esempio si può generare una eccezione quando:
 Un file che si tenta di aprire non esiste
 La connessione di rete non è più disponibile
 Gli operandi da manipolare hanno valori in un intervallo non più lecito
 Si tenta di accedere ad una classe il cui file per qualche motivo è mancante
1. public class HelloWorld{
2.
public static void main (String args []){
3.
int i=0;
4.
String greetings [] = {“Hello World!”, “No, I Mean it!”,
5.
“HELLO WORLD!”};
6.
while( i < 4 ){
7.
System.out.println(greetings[i]);
8.
i++;
9.
}
10.
}
11. }
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
63
Modulo 8
Eccezioni (Exceptions)
Il risultato dell’esecuzione del programma precedente è:
C:\Documenti\JavaCourse>java HelloWorld
Hello World!
No, I Mean it!
HELLO WORLD!
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
at HelloWorld.main(HelloWorld.java:7)
La possibilità della gestione delle eccezioni consente ad un programma di catturarle,
maneggiarle opportunamente e continuare l’esecuzione. Essa è strutturata in maniera tale che
gli errori a runtime non lasciano che il programma fuoriesca dal normale flusso di esecuzione.
Le eccezioni sono gestite nello stesso istante in cui avvengono, tramite blocchi di istruzioni
separati, associati al normale codice per l’esecuzione del programma.
Istruzioni try e catch
Per maneggiare una particolare eccezione, includere all’interno di un blocco try il codice
opportuno, e creare una lista di blocchi catch aggiuntivi, uno per ogni possibile eccezione che
può essere generata. Se, durante l’esecuzione del blocco di istruzioni try, viene generata una
delle eccezioni corrispondente ad una di quelle listate nelle istruzioni catch, il relativo codice
sarà eseguito per gestire l’eccezione. E’ possibile inserire più di un blocco catch affinché si
possano gestire tipi di errori diversi.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
64
Modulo 8
Eccezioni (Exceptions)
Istruzioni try e catch
Esempio HelloWorld.
1. public class HelloWorld{
2.
public static void main (String args []){
3.
int i=0;
4.
String greetings [] = {“Hello World!”, “No, I Mean it!”,
5.
“HELLO WORLD!”};
6.
while( i < 4 ){
7.
try{
8.
System.out.println(greetings[i]);
9.
}catch(ArrayIndexOutOfBoundsException ex){
10.
System.out.println(“Error: greetings size is < ”+i);
11.
}
12.
i++;
13.
}
14.
}
15. }
C:\Documenti\JavaCourse>java HelloWorld
Hello World!
No, I Mean it!
HELLO WORLD!
Error: greetings size is < 3
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
65
Modulo 8
Eccezioni (Exceptions)
In Java esistono tre ampie categorie di eccezioni. La classe java.lang.Throwable funge da
classe genitore per tutti gli oggetti ti tipo Exception che possono essere lanciati e catturati
usando il meccanismo di gestione delle eccezioni. I metodi definiti nella classe Throwable
recuperano il messaggio di errore associato con l’eccezione e stampano lo stack trace
(tracciamento) che mostra dove l’eccezione è avvenuta. Le tre sottoclassi fondamentali di
Throwable sono: Error, Exception, and RunTimeException.
Exception Categories
Throwable
Error
VirtualMachineError
Exception
AWTError
RunTimeException
IOException
OutOfMemoryError
ArithmeticException
EOFException
StackOverflowError
NullPointerException
............
............
FileNotFoundExcption
IndexOutOfBoundException
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
66
Modulo 8
Eccezioni (Exceptions)
La regola Gestire o Dichiarare (una eccezione)
Per caldeggiare la scrittura di codice robusto, Java richiede che se avviene una eccezione mentre
un metodo si trova sullo stack (cioè è stato invocato), il chiamante del metodo deve determinare
quale azione intraprendere in caso di eccezione.
Per soddisfare queste richieste il programmatore può fare le seguenti due scelte:
 Lasciare che il metodo che ha generato l’eccezione la gestisca includendo nel suo
codice i blocchi try{} catch(){}. In questo modo l’eccezione è gestita
completamente, anche se il blocco relativo al catch è vuoto.
 Fare in modo che il metodo che ha generato l’eccezione non la gestisca rilanciandola
indietro al metodo chiamante. Per fare questo è necessario marcare la dichiarazione
del metodo con la parola riservata throws come mostrato di seguito:
public void callsTroubleSome() throws IOException
La parola throws può essere seguita da uno o più nomi di eccezioni separati da virgole che il
metodo può rilanciare al suo chiamante.
La scelta di gestire o dichiarare una eccezione dipende da cosa il programmatore ritiene più
opportuno.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
67
Modulo 9
Modulo 9: Realizzare una GUI
Package AWT (Abstract Windowing Toolkit)
 Fornisce i componenti grafici di base usati in tutte le applicazioni
Java per realizzare le GUI (Graphic User Interface).
 Contiene delle classi che possono essere estese, e le loro proprietà
ereditate.
 Assicura che ogni componente GUI visualizzato sullo schermo sia
una sottoclasse della classe astratta Component.
 Comprende Container, una classe astratta, sottoclasse di
Component ed include due sottoclassi:
1. Panel
2. Window
AWT fornisce la possibilità di creare interfacce grafiche il cui aspetto è molto simile fra le diverse
piattaforme esistenti.
Ogni componente GUI che appare sullo schermo è una sottoclasse della classe astratta Component.
Ovvero, ogni oggetto grafico che estende la classe Component condivide con gli altri tutti i metodi
e le variabili di classe che consentono loro di lavorare.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
68
Modulo 9
Il package java.awt
The java.awt Package
java.lang.Object
Panel
Applet
BorderLayout
CardLayout
CheckboxGroup
Color
Dimension
Event
Font
GridLayout
Toolkit
GridbagLayout
Component
Button
Canvas
CheckBox
Choice
Container
Label
List
TextComponent
Window
Dialog
ScrollPane
TextArea
TextField
Frame
FileDialog
MenuBar
Menu
MenuItem
Menu
Popup
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
69
Modulo 9
Containers
Vi sono due tipi principali di containers: Window e Panel.
 Una Window è una finestra nativa visualizzabile sullo schermo, indipendente da altri
contenitori.
Due sono le sottoclassi più importanti: Frame e Dialog.
1. Frame è una finestra che contiene un titolo ed ha gli angoli per ridimensionarla.
2. Dialog non ha barra per i menu, si può muoverla ma non ridimensionarla.

Un Panel è contenuto sempre in un altro Container, o in una Applet. Un Panel
identifica una area rettangolare in cui disporre altri componenti. Panel, per poter essere
visualizzato, deve essere disposto dentro una Window (o una sua sottoclasse).
Panel
Frame
Frame
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
70
Modulo 9
Realizzazione di una GUI
 La posizione e la dimensione dei componenti in un Container è determinata da un layout
manager. Quando in un Container si deve posizionare un componente, interviene per farlo il
layout manager. Lo stesso avviene quando è necessario determinare la dimensione di un
componente. Il layout manager possiede il controllo completo su tutti i componenti contenuti nel
Container. Esso è responsabile del calcolo e della definizione delle dimensioni ottimali nel
contesto delle particolari dimensioni dello schermo.
 Al contrario è anche possibile disabilitare il layout manager ed avere in proprio il controllo
completo dei componenti invocando il metodo:
container.setLayout(null);
In questo caso, per posizionare gli oggetti è necessario usare i metodi setLocation(),
setSize(), o setBounds() sui componenti che del container.
Bisogna considerare in questo caso che il risultato potrebbe differire fra una piattaforma e l’altra
a causa delle differenze nei vari sistemi di finestre e dimensione dei font.
L’ approccio migliore è quello di usare un Layout Manager.
Java è provvisto dei seguenti layout manager:





FlowLayout – layout manager predefinito per Panel ed Applet.
BorderLayout – layout manager predefinito per Window e Panel.
GridLayout
CardLayout
GridBagLayout
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
71
Flow Layout Manager: un esempio ExGui.java
import java.awt.*;
new Frame(“GUI Example”)
Questo metodo crea una istanza della classe Frame. Se
non diversamente specificato Frame ha dimensioni 0x0
e non è visibile.
public class ExGui{
private Frame f;
private Button b1;
private Button b2;
public void go(){
f = new Frame("GUI Example");
f.setLayout(new FlowLayout());
b1 = new Button("Press Me");
b2 = new Button("Don't Press Me");
f.add(b1);
f.add(b2);
f.pack();
f.setVisible(true);
}
public static void main(String [] s){
ExGui guiWin = new ExGui();
guiWin.go();
}
}
Ignazio Testoni
Modulo 9
f.setLayout(new FlowLayout);
Questo metodo crea una istanza della del layout
manager flow layout e lo installa nel Frame. Il
FlowLayout manager è il più semplice per AWT e
dispone i componenti orizzontalmente o verticalmente.
f.add(b1);
Indica al Frame f (che è un container) che deve
accludere in sé il componente b1. La dimensione e
posizione di b1 sono sotto il controllo del layout
manager del Frame f.
f.pack();
Indica al frame di disporre i propri componenti in
maniera tale da renderli tutti visibili ed in ordine. Per
determinare quali dimensioni usare per i componenti,
f.pack() interroga il proprio layout manager,
responsabile per le dimensioni e posizione di tutti i
componenti contenuti nel Frame.
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
72
Flow Layout Manager: un esempio





Modulo 9
Il FlowLayout usato in questo esempio posiziona i componenti riga dopo riga. Quando lo
spazio disponibile su una riga si esaurisce i nuovi componenti vengono disposti sul una nuova
riga successiva.
Il FlowLayout, unlike other layout managers, does not constrain the size of the components it
manages, but instead allows them to have preferred size.
Gli argomenti del costruttore di FlowLayout consentono di specificare se allinerae gli
elementi da sinistra verso destra o viceversa oppure di tenerli centrati.
Si può specificare lo spazio vuoto minimo fra i componenti.
Se l’area gestita da un FlowLayout viene ridimensionata dall’utente, il layout può cambiare.
FlowLayout: ridimensionamento
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
73
Modulo 9
Grid Layout Manager



Il GridLayout manager un po’ più di flessibilità per disporre i componenti. I componenti
sono disposti in una matrice con un certo numero di righe e di colonne. I componenti riempiono
le celle definite dal manager.
La posizione relativa dei componenti non cambia se l’intera area è ridimensionata. Cambia solo
la dimensione dei singoli componenti.
Il GridLayout manager ignora sempre la dimensione ottimale dei componenti. L’altezza e la
larghezza delle celle è uguale per tutte ed è determinata dividendo l’altezza e la larghezza totale
disponibile per il numero di righe e di colonne.
import java.awt.*;
public class GridExample{
GridLayout gl = new GridLayout(4,3);
public GridExample(){
Frame f = new Frame("GridLayout Example");
f.setLayout(gl);
for(int c=9;c>=0;c--){
f.add(new Button(""+c));
}
f.add(new Button("+/-"));
f.add(new Button(","));
f.pack();
f.setVisible(true);
}
public static void main(String [] s){
GridExample g = new GridExample();
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
74
Modulo 10: Gestione degli eventi
Modulo 10
Quando un utente compie un’azione su una interfaccia grafica (cliccare sul mouse, premere un
tasto, ingrandire una finestra, etc.), viene generato un Evento.
Gli Eventi sono modellizzati tramite degli oggetti che descrivono che cosa è accaduto. Per
descrivere le varie categorie di azioni che un utente può provocare, esiste in java una
molteplicità di classi Event già predefinite.
I soggetti coinvolti nella generazione e nella gestione di un evento sono:
 Event – Oggetti che descrivono che cosa è accaduto.
 Event sources – Oggetti che generano gli eventi.
Un esempio di Event source è un oggetto di tipo Button che genera un evento di tipo
ActionEvent che contiene informazioni sull’evento. ActionEvent possiede i metodi:
 getActionCommand() – restituisce un oggetto String associato all’azione compiuta
 getModifiers() – restituisce eventuali tasti modificatori premuti (ctrl, alt, shift …).
 Event handlers – Uno o più metodi che ricevono un oggetto di tipo evento, lo decifrano e
consentono l’interazione con l’utente.
Nel caso di ActionEvent il metodo ad esso associato per gestire l’evento è:
 actionPerformed() – contiene le istruzioni da eseguire in seguito alla generazione
dell’evento.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
75
Modulo 10
Delegation Model: i Listener
Il meccanismo chiamato “Delegation Model” consiste nel delegare una classe opportuna alla
gestione dell’evento generato. Cioè, il componente che ha originato l’evento lo propaga ad una o
più classi registrate dette listener.
 Ogni listener deve essere registrato nell’oggetto che genera l’evento.
 I listener contengono gli event handlers che ricevono l’evento generato e lo processano
eseguendo le azioni necessarie.
 I listener devono implementare una interfaccia di tipo EventListener o una sua sottoclasse.
 Gli oggetti di tipo evento sono propagati esclusivamente ai listener registrati.
 Ogni tipo di evento possiede una corrispondente interfaccia di tipo listener che obbliga la
classe che la implementa a definire tutti i suoi metodi.
 Se un componente genera un evento ma non ha nessun listener registrato, l’evento non viene
propagato.
Event handler relativo a Panel e Frame
Evento di tipo ActionEvent
public void actionPerformed (ActionEvent e) {
frame.close(); // Chiude la finestra
Action handler
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
76
Delegation Model: un esempio
Modulo 10
package corso;
// TestButton.java
import java.awt.*;
 La classe Button ha il metodo addActionListener()
public class TestButton {
che consente al listener di essere registrato.
public TestButton() {
 L’interfaccia ActionListener definisce un solo
}
metodo, actionPerformed(), che riceve un evento
public static void main(String [] s){
ActionEvent.
Frame frame = new Frame("Test");
Button button = new Button("Premere!");
 Il listener registrato deve implementare
button.addActionListener(new ButtonHandler());
l’interfaccia ActionListener.
frame.add(button);
frame.pack();
frame.setVisible(true);
}
}
package corso;
// ButtonHandler.java
Action handler
import java.awt.event.*;
 Un click sul Button genera un ActionEvent
public class ButtonHandler implements ActionListener {
che viene ricevuto da actionPerformed(),
public ButtonHandler() {
metodo di ButtonHandler che è registrato
come listener sul Button.
}
public final void actionPerformed(final ActionEvent actionEvent) {
 Il metodo getActionCommand() della classe
System.out.println("Attenzione! Evento di tipo Action!");
ActionEvent restituisce il nome del comando
System.out.println("Il pulsante premuto e':"+
associato all’azione. Nel caso di Button esso
actionEvent.getActionCommand()+"\n");
restituisce la sua etichetta (label).
}
}
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
77
Modulo 10
Tipologie di eventi ed interfacce
Categoria
Interfaccia
Metodi
Action
ActionListener
actionPerformed(ActionEvent)
Item
ItemListener
itemStateChanged(ItemEvent)
Mouse motion
MouseMotionListener
mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
Mouse button
MouseListener
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mouseClicked(MouseEvent)
Key
KeyListener
keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
Focus
FocusListener
focusGained(FocusEvent)
focusLost(FocusEvent)
Window
WindowListener
windowClosing(WindowEvent)
windowOpened(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
windowClosed(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
Text
TextListener
textValueChanged(TextEvent)
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
78
Modulo 10
Gli Event Adapters
Ogni volta che si implementa un’interfaccia bisogna necessariamente implementare tutti i suoi metodi.
Naturalmente questo vale anche per i listener. A volte può essere piuttosto noioso implementare diversi
metodi anche se poi non li si utilizza. Per esempio questo accade frequentemente con le interfacce
MouseListener e WindowListener che dichiarano rispettivamente 5 e 7 metodi per la gestione dei
vari eventi .
Allo scopo di facilitare il programmatore, java fornisce alcune classi che implementano
automaticamente tutti i metodi della relativa interfaccia dichiarata.
Queste classi sono dette Adapter classes e ne esiste una per ogni listener che dichiara più di un
metodo.
Per esempio:
 MouseAdapter
 WindowAdapter
 ComponentAdapter
 FocusAdapter
import java.awt.*;
Mouse click handler
import java.awt.event.*;
public class MouseClickHandler extends MouseAdapter {
// Serve solo la gestione del click
public final void mouseClicked(MouseEvent mouseEvent) {
// Overriding del metodo omonimo della classe MouseAdapter
}
}
Per poterle utilizzare basta creare una nuova classe che estende l’adapter opportuno.
A questo punto serve solo reimplementare, attraverso l’overriding, il metodo o i metodi (event
handler) che si intende sfruttare.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
79
Modulo 11
Modulo 11: La calcolatrice
Tramite lo studio di questo programma vedremo applicati tutti i principali argomenti trattati nel
presente corso.
Il programma si basa sulla tecnica Model-View-Control e consta delle seguenti classi:
1.
Calculator.java
=>
View
2.
EventHandler.java
=>
Control
3.
Operation.java
4.
OperationDivide.java
5.
OperationMultiply.java
6.
OperationSubtract.java
7.
OperationSum.java
La classe Calculator si occupa della creazione dell’interfaccia grafica e contiene il metodo
main(String [] s).
La Classe EventHandler si occupa della gestione completa di tutti gli eventi generati dalla GUI.
La classe astratta Operation rappresenta una delle 4 operazioni a due operandi (+,-,*,/) e viene estesa
dalle quattro classi Operation rimanenti. In funzione della operazione selezionata tramite la GUI, il
programma esegue il metodo getResult() della classe corrispondente (polimorfismo).
Le rimanenti operazioni che lavorano solo su un operando effettuano il calcolo nell’istante in cui
viene premuto il relativo pulsante.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
80
La GUI
Modulo 11
L’interfaccia grafica consiste in un Frame che ha un BorderLayout
come layout manager.
Il Frame contiene al suo interno:
• Una Label che ne rappresenta il display disposto nella posizione
NORTH
• Un Panel contenente la Label per la memoria ed i tre pulsanti
per azzerare il display, disposto nella posizione CENTER
Il Panel a sua volta ha un FlowLayout come layout manager.
• Un Panel contenente il resto dei pulsanti disposto nella
posizione SOUTH.
Il Panel a sua volta ha un GridLayout come layout manager.
I pulsanti nel GridLayout sono
contenuti in una struttura dati di
tipo Hashtable con una
associazione chiave – valore.
La chiave è rappresentata
dall’etichetta, il valore è il
corrispondente oggetto Button.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
81
Modulo 11
EventHandler
La classe EventHandler estende WindowAdapter ed implementa ActionListener.
Estendere WindowAdapter consente di dover reimplementare solo uno dei 7 metodi dichiarati, cioè
windowClosing(), per poter chiudere il programma chiudendone semplicemente la finestra cliccando con il
mouse sul tasto di chiusura della finestra stessa.
L’implementazione dell’interfaccia ActionListener ci obbliga a dover definire ed implementare il metodo
actionPerformed() dove sono descritte tutte le operazioni da effettuare in corrispondenza della pressione di
ciascun Button.
La classe EventHandler viene registrata come Listener sia nel Frame per gli eventi generati dal Frame
sia in ciascun Button per gli eventi generati da tutti i Button.
La stringa actionCommand contiene
l’etichetta del pulsante che è stato premuto.
In funzione del valore di actionCommand
vengono eseguite le istruzioni opportune.
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007
82
Java programming Language
Continua …
Ignazio Testoni
Ordine degli Ingegneri Provincia di Catania
29 giugno – 7 luglio 2007