3. Funzionale, Procedurale e ad Oggetti
•Funzionale (detta anche orientata alle espressioni): si focalizza
sulle espressione e considera le funzioni come oggetti.
• Es: Python
•Procedurali (o imperativi): il focus è sulla sequenza di operazioni
da eseguire
• Es: C, VB Classic, Pascal, Fortran, Algol, C++
•Programmazione ad Oggetti (OO): il dominio viene astratta in
elementi aventi un proprio stato ed una serie di metodi in grado di
lavorare su di esso.
• Es: Java, C#, C++
4. Sintassi vs Semantica
•La sintassi definisce la forma: come e’ fatto un
programma del linguaggio (correttezza sintattica)
• La semantica definisce il significato associato a
ciascuna forma: cosa calcola ciascun programma
(correttezza semantica)
5. Il nostro focus
Al centro di questo corso introduttivo vedremo i
concetti di base della programmazione ad oggetti.
Ragioneremo in modo “agnostico” rispetto allo
specifico linguaggio, ma utilizzeremo JAVA per gli
esempi
6. Perché Object Oriented
• La programmazione ad oggetti rappresenta una metodologia di
sviluppo software che si contrappone alla programmazione procedurale,
spesso troppo poco gestibile e confusionaria.
•Tramite l'approccio orientato ad oggetti è possibile definire delle classi
che rappresentano un tipo di dato gestito dall'applicazione che può
essere utilizzato solo tramite particolari interfacce esposte dalla classe
stessa verso le altre classi dell'applicazione. All'interno di una classe
esistono infatti alcune funzionalità "interne" che non vengono mostrate
all'esterno.
•Tramite questa tipologia di programmazione si migliora notevolmente il
codice limitando le interferenze tra diversi componenti e incapsulando
funzionalità specifiche all'interno di una sorta di contenitore che
permette una organizzazione più funzionale ed elegante.
7. Classi,Interfacce e Classi Astratte (1)
•I linguaggio OO trovano nella “classe” il loro
elemento principale
•una classe definisce tipicamente un tipo
•Istanziando una classe (in sintesi allocando
memoria per essa) otteniamo un oggetto di
quello specifico tipo
8. Classi,Interfacce e Classi Astratte (2)
• Le interfacce rappresentano un “contratto”, ovvero una
serie di funzionalità che la classe deve implementare se
vuole essere conforme a quanto definito
• per ogni interfaccia possono esistere più classi che la
implementano
• e quindi, transitivamente, posso riferirmi a oggetti di
classi diverse che implementano la stessa interfaccia
tramite quest’ultima
Tramite le interfacce (ed una serie di pattern) posso
ottenere una vera “dinamicità” del codice!
9. Classi,Interfacce e Classi Astratte (3)
•Le interfacce permettono di astrarre quello che è
richiesto ad una classe da come esso viene
implementato.
• Ciò consente di disaccoppiare i due elementi,
consentendo di utilizzare l’opportuno implementazione
senza modificare (o quasi) il flusso primario di
esecuzione del codice.
design for change
10. Classi,Interfacce e Classi Astratte (4)
• Le classi astratte sono un po’ una via di mezzo tra Classi
ed Interfacce. Infatti consentono di implementare in modo
completo una serie di operazioni (metodi) e definire il
contratto di altre che dovranno essere implementate dalle
classi figlie.
Le classi astratte non sono istanziabili!
11. Caratteristiche fondamentali di
un linguaggio Object Oriented
•incapsulamento: la classe è un “mondo a se”, auto contenuto e
portatore di una (o più) informazione (i) ben precisa (e).
•ereditarietà: la possibilità di estendere classi con altre classi che ne
ereditano appunto proprietà e metodi;
•polimorfismo: la possibilità di avere funzionalità particolari che si
comportano in maniera diversa in base all'oggetto invocante o ai
parametri ad esso passati.
12. Struttura di una Classe
Una classe realizza l'implementazione di un tipo
di dato astratto. class Animal
{
string family;
int legs;
string GetFamily()
{
return family
}
void SetFamily(string fam)
{
this.family = fam;
}
…
}
13. Object Oriented: Ereditarietà (1)
•L'ereditarietà consente di definire un tipo (ovvero una nuova
classe) estendendone uno già esistente ed ereditando le sue
proprietà (dati e metodi)
•La classe di partenza è la “classe base” (“superclasse“, “classe
padre”), la nuova classe è detta “classe derivata” (“sottoclasse”,
“classe figlia”).
14. Object Oriented: Ereditarietà (2)
class Padre {
int x = 5;
}
public class Figlio extends Padre { PADRE
public static void main(String[] args) {
Figlio pr = new Figlio();
pr.leggo();
}
void leggo() { FIGLIO
System.out.println(x);
}
}
La classe Figlio eredita la proprietà x dalla classe Padre e può usarla al suo interno
15. Object Oriented: Polimorfismo (1)
•Il polimorfismo consente di utilizzare un’unica interfaccia per
richiamare funzionalità varianti in base ad una specifica
situazione (implementazione)
•Mentre con gli oggetti il collegamento con la classe avviene a
compile-time, nel caso del polimorfismo avviene a run-time
•Il polimorfismo viene impiegato impiegando una interfaccia, una
classe astratta o una classe e richiede che le stesse siano collegate
tra loro tramite ereditarietà
Il termine “polimorfismo” deriva dal greco e significa
“pluralità di forme”
16. Object Oriented: Polimorfismo (2)
abstract class Figura
{
abstract void rispondo(); Figura
}
class Triangolo extends Figura Triangolo Rettangolo
{
void rispondo(){System.out.println("Sono il
triangolo");}
}
class Rettangolo extends Figura
{
void rispondo(){System.out.println("Sono il
rettangolo");}
}
17. Object Oriented: Polimorfismo (3)
public class Altro
{
Figura pr;
public static void main(String[] args)
{
Altro al = new Altro();
al.metodo();
}
void metodo()
{
pr = new Triangolo();
pr.rispondo();
pr = new Rettangolo();
pr.rispondo();
}}
Assegno alla stessa classe astratta oggetti di tipo diverso. La cosa è
possibile grazie all’ereditarietà
20. Classi e oggetti
La classe modella un insieme di oggetti omogenei (le istanze
della classe) ai quali sono associate proprietà statiche e
dinamiche
Ogni classe è descritta da:
• Nome della classe (l’identificatore)
• Attributi (lo stato)
• Operazioni (il comportamento)
Importanza dell'identificativo
•Due oggetti con identificativi distinti sono comunque distinti,
anche se hanno i valori di tutti gli attributi uguali
•Due oggetti diversi devono avere identificativi diversi, anche
se possono avere gli stessi valori per tutti gli attributi
21. Attributi e metodi (1)
Le classi sono tipicamente caratterizzate da:
• attributi
•modellano una o più proprietà della classe
•tipicamente rappresentano nel loro insieme lo
stato dell’oggetto
• metodi
•permettono operazioni sugli attributi
•permettono di variare lo stato dell’oggetto
22. Attributi e metodi (2)
In una classe, un metodo si definisce specificando i
parametri e il tipo del risultato (se c‟è).
Non è necessario che un metodo restituisca un valore o un
oggetto. Un metodo può anche effettuare solamente
azioni senza calcolare un risultato.
23. Attributi e metodi (3)
I metodi possono essere raggruppati in due macro-categorie:
• Funzione: elaborano i dati e restituiscono un valore
int moltiplicavalori(int a, int b) {
risultato= a * b;
return(risultato);
}
• Procedure: eseguono la procedura e non
restituiscono un valore
void nomeMetodo(int a, int b) {
System.out.println(a+” - “+b );
}
24. Attributi e metodi, funzioni (4)
• int è il tipo di valore che la funzione restituirà(quindi il tipo della
variabile risultato);
• moltiplicavalori è il nome della funzione;
• argomenti: all'interno delle parentesi tonde troviamo i due
argomenti che forniamo alla funzione con i loro relativi tipi
• blocco di istruzioni : all'interno delle parentesi graffe troviamo
il blocco di istruzioni della funzione
• return: l'istruzione return(...) è quella che permette alla funzione
di restituire il valore risultato. Le istruzioni che seguono
l'istruzione return vengono ignorate
25. Attributi e metodi, procedure (5)
• nomeMetodo: è il nome della funzione;
• argomenti: all'interno delle parentesi tonde troviamo i due argomenti
che forniamo alla funzione con i loro relativi tipi
• blocco di istruzioni: all'interno delle parentesi graffe troviamo il
blocco di istruzioni della funzione
• void (vuoto): indica che la funzione non restituirà nessun valore ma
eseguirà solamente le istruzioni indicate
• l'istruzione: System.out.println(...) è quella che permette alla funzione
di visualizzare a console i parametri passati
26. Attributi e metodi(6)
Le proprietà sono collegate ai tipi, che posso essere :
primitivi: si prestano ad un uso intuitivo
reference: fanno riferimento ad oggetti, array, ecc
A seconda della modificabilità, possono essere.
Costanti (variabili final): dati che non possono subire alcuna modifica
Variabili : dati suscettibili di modificazione
A seconda della globalità possono essere:
• static : le modifiche apportate da un oggetto a questi dati si propagano a
tutte le istanze di quell’oggetto
• di istanza: le modifiche apportate non si ripercuotono alle altra istanze
27. Costruttori
Il costruttore è un metodo che viene eseguito quando si
istanzia una classe.
public class MiaClasse
public MiaClasse() {
//blocco di istruzioni
}
}
•public: è necessario che sia accessibile per instanziare la classe
•MiaClasse: ha lo stesso nome della classe
•blocco di istruzioni: sono le istruzioni che implementiamo
Possono esistere più metodi costruttori con diversi tipi e quantità di
parametri (overloading)
29. Incapsulamento dei dati
L'incapsulamento permette di gestire (e nascondere) in modo mirato
variabili (dati) interni alla classe, legando il loro acceso e la loro modifica
all’utilizzo di una funzione (metodo) che effettui quanto richiesto in
accordo con le regolo proprie dell’oggetto e del dominio relativo
In questa classe possiamo notare che la proprietà x privata è
accessibile in scrittura dal metodo
scrivo() ed in lettura dal class MiaClasse {
private int x;
metodo leggo()
public int leggo() {
return x;
}
public void scrivo(int x) {
this.x = x;
}
}
30. Overloading e Overriding (1)
•L‘Overloading consente di definire in una stessa classe più metodi
aventi lo stesso nome, ma che differiscano nella firma, cioè nella
sequenza dei tipi dei parametri formali. È il compilatore che determina
quale dei metodi verrà invocato, in base al numero e al tipo dei parametri
attuali.
•L‘Overriding, invece, consente di ridefinire un metodo in una
sottoclasse: il metodo originale e quello che lo ridefinisce hanno
necessariamente la stessa firma, e solo a tempo di esecuzione si determina
quale dei due deve essere eseguito.
31. Overloading e Overriding (2)
Esempio di overloading:
class Esempio {
int prop;
public void metodo() { codice };
public int metodo() {
return prop;
}
}
Esempio di overriding:
class Esempio2 exends Esempio
{
public void metodo() { codice2 };
}
32. Boxing e Unboxing
Viene utilizzato per assegnare ad un oggetto un tipo primitivo
senza ricorrere a metodi di utility.
Consente di velocizzare lo sviluppo di codice e di ottimizzare
le prestazioni:
//senza boxing
Integer i1 = new Integer(100);
int y1 = 20;
int z1 = y1 + i1.intValue();
//con boxing
Integer i2 = 100;
int y2 = 20;
int z2 = y2 + i2;
34. Il linguaggio JAVA (1)
Java si caratterizza per una miriade di specificità. Tra le più
evidenti troviamo:
• orientato agli oggetti
• eseguito in un ambiente protetto, ovvero dalla Java Virtual
Machine (JVM)
• indipendente dalla piattaforma, portabile
• sicuro dal punto di vista della gestione del codice
• multithreading
• dinamico
Java è stato creato da James Gosling ed il proprio team di ingegneri
presso la Sun Microsystems, oggi acquisita da Oracle.
35. Il linguaggio JAVA (2)
• Java è ad “oggetti puro”, quindi non object based come ad
esempio il C++
• Non contempla l’aritmetica dei puntatori
• Non è necessario deallocare la memoria in modo esplicito
(esiste il meccanismo del “garbage collection”)
• Non prevede ereditarietà multipla (solo singola)
In realtà in alcuni casi è comunque utile deallocare la memoria,o
meglio le risorse utilizzate, in modo esplicito.
36. Il linguaggio JAVA (3)
•Con i linguaggi compilati in modo nativo, per effettuare il
porting su piattaforme diverse, è necessario utilizzare lo
specifico compilatore e ricompilare il codice… sperando di
non dover apportare modifiche!
37. Il linguaggio JAVA (4), JVM
Write Once, Run Anywhere
•Il codice Java viene compilato in un linguaggio
intermedio chiamato bytecode indipendente dalla
macchina (calcolatore) su cui viene eseguito.
•javac (comando) compila il codice sorgente .java i
bytecode .class.
•Il Bytecode, successivamente viene interpretato da
una specifica Java Virtual Machine (JVM).
•Il Bytecode non è altro che una serie di istruzioni da
eseguire passo-passo.
38. Il linguaggio JAVA (5), JVM
• La JVM è, semplificando, un computer
simulato/virtualizzato in un computer host;
• La JVM trasforma il bytecode nello specifico
linguaggio macchina della piattaforma di destinazione
•Esistono differenti JVM per differenti piattaforme:
•Windows, Mac OS X, Linux, cellulari.
•Per la stessa piattaforma esistono JVM realizzati da
diversi produttori
•Sun/Oracle, Microsoft, ecc.
40. Il linguaggio JAVA (6), Dinamico
• Il linking (collegamento) delle classi avviene solo
quando richiesto
• Le classi sono normalmente “depositate” su disco
locale o sulla rete
•Il codice viene sempre verificato prima di essere
passato all’interprete per l’esecuzione.
•E’ possibile aggiungere nuovi metodi e variabili di
istanza ad una classe, senza dover ricompilare
l’intera applicazione
41. Il linguaggio JAVA (7), MultiThreading
•Elaborazioni simultanee in un ambiente a singolo
processo
•La gestione dei thread in genere e di tipo preemptive
•Nei sistemi in cui la gestione è non preemptive Java
fornisce il metodo yield() che dà, ad un altro thread,
la possibilità di essere comunque eseguito
•I metodi dichiarati synchronized non possono essere
eseguiti simultaneamente da più thread;
42. Il linguaggio JAVA (8), Sicuro
•Il compilatore esegue una serie di verifiche durante la
generazione del bytecode:
1. controlli di errori di codifica
2. verifica dichiarazioni di tipo esplicite e non implicite
3. le classi sono inserite in un name-space per gestire la
sicurezza
•Inoltre (cosa ripetuta a tempo di esecuzione), viene inibito il
codice potenzialmente pericoloso
43. Compilazione ed esecuzione (1)
Primo programma in JAVA
• Un programma Java è costituito da una o più classi
• Ogni classe risiede in un file che ha lo stesso nome della
classe ed estensione .java
• Deve esistere almeno una classe che ha il nome del
programma ed un metodo speciale chiamato main.
44. Compilazione ed esecuzione (2)
public class HelloWorld
{
public static void main (String args[])
{
System.out.println(“Hello”);
}
}
45. Compilazione ed esecuzione (2b)
Per compilare ed eseguire la classe HelloWord
C:SorgentiHelloWorldjavac HelloWorld.java
C:SorgentiHelloWorldjava HelloWorld
Hello
C:SorgentiHelloWorld
46. Compilazione ed esecuzione (3)
•Il metodo main deve essere sempre presente,
unico e serve per avviare l’applicazione.
•Non viene utilizzato per le Applet o le servlet.
public static void main(String [] args) {
//blocco di istruzioni
}
47. Compilazione ed esecuzione (4)
• public: è necessario che sia accessibile per poter avviare
la classe
• static: è un metodo di classe
• void: non restituisce nessun valore
• main: nome del metodo principale,
• String [] args: Array di stringhe usato come parametro
(obbligatorio)
• blocco di istruzioni: sono le istruzioni che
implementiamo
49. Tipi Primitivi (1)
Il JDK viene fornito con una serie comune di Tipi Primitivi
Tipo Primitivo Dimensione
boolean valori che possono essere true e false
i caratteri, sono di 16 bit, e sono
char codificati Unicode 1.1.5, negli altri
linguaggi sono ASCII, di soli 8 bit
interi di 8 bit con segno, ovvero numeri
byte compresi tra meno (due alla settima) e
due alla ottava
short interi di 16 bit con segno
int interi di 32 bit con segno
long interi di 64 bit con segno
reali di 32 bit in virgola mobile (IEEE 754-
float
1985)
reali di 64 bit in virgola mobile (IEEE 754-
double
1985)
50. Tipi Primitivi (2)
•Per garantire la portabilità del Bytecode da una piattaforma ad un‟altra
Java fissa le dimensioni di ogni dato primitivo
•I tipi primitivi mantengono le loro dimensioni in tutte le piattaforma
grazie al fatto che le JVM devono essere implementate secondo specifiche
ben definite
Tipo Primitivo Dimensione
Boolean 1bit
Char 16bit
Byte 8bit
Short 16bit
Int 32bit
Long 64bit
Float 32bit
Double 64bit
51. Tipi Primitivi, Numeri interi
•Il tipo int è senza dubbio il tipo primitivo più usato, per ragioni di
praticità e di efficienza. Può contenere qualunque numero intero compreso
tra 2.147.483.647 e -2.147.483.648, ossia tutti i numeri rappresentabili con
una cella di memoria a 32 bit
•Il tipo byte permette di operare su numeri compresi tra -128 e 127, che
sono i numeri che è possibile rappresentare con cifre da 8 bit
•Il tipo short permette di trattare numeri a 16 bit, compresi tra -32768 e
32767: è in assoluto il formato meno usato in Java
•Il tipo long a 64 bit, che permette di trattare numeri compresi tra -
9.223.327.036.854.775.808 ed 9.223.327.036.854.775.807. è necessario
posporre al numero la lettera 'L'
52. Tipi Primitivi, Numeri floating point
•Il tipo float, a 32 bit, può contenere numeri positivi e negativi
compresi tra 1.40129846432481707*10^-45 e
3.4282346638528860*10^38
•Il tipo double a 64 bit può lavorare su numeri positivi e negativi tra
4.94065655841246544*10^-324 e 1.79769313486231570*10^138
•float number = 1.56e3F;
•double bigNumber = 5.23423e102;
53. Tipi Primitivi, boolean
•Una variabile booleana può assumere solamente due valori: “true” o
“false”
• boolean a = true;
• boolean b = false;
•Il ricorso agli operatori relazionali '==', '!=', '>', '<',
• '>=' e '<=', permette di assegnare ad una variabile
• booleana il valore di verità di un'espressione.
Ad esempio:
•boolean b = (a == 10);
• assegna a b il valore di verità dell'espressione a ==
• 10, che sarà 'true' se la variabile 'a' contiene il valore
• 10, 'false' in caso contrario
54. Tipi Primitivi, char (1)
•Il tipo “char”può contenere un carattere in formato
Unicode che comprende decine di migliaia di caratteri, vale
a dire gli alfabeti più diffusi nel mondo.
•I valori da 0 a 127 corrispondono, per motivi di retro
compatibilità, al set di caratteri ASCII
•Il tipo char è un intero a 16 bit privo di segno, pertanto esso
può assumere qualunque valore tra 0 e 65535
55. Tipi Primitivi, char (2)
Il carattere speciale “” ha il ruolo di specificare alcuni
caratteri che altrimenti non sarebbe possibile specificare con
la tastiera
• 'n'nuova linea
• 'r'a capo
• 'f'nuova pagina
• '''carattere apice
• '"'carattere doppio apice
• ''carattere backslash
• 'b'backspace
• 't'carattere di tabulazione
56. Tipi Primitivi, Casting: up and down
up-casting: se la variabile destinazione è più capace di
quella di partenza
• byte b = 100;
• short s = b; // promozione da byte a short
• int i = s; // promozione da short a int
• long l = i; // promozione da int a long
down-casting: se la variabile destinazione è meno
capace di quella di partenza
• long l = 100;
• int i = (int)l; // cast da long a int
• short s = (short)i; // cast da int a short
• byte b = (byte)s; // cast da short a byte
57. Le stringhe alfanumeriche (1)
In Java è possono utilizzare e gestire stringhe
tramite le due classi:
• String: un oggetto di tipo String è una stringa costante
• StringBuffer: un oggetto di tipo StringBuffer è una stringa variabile nel
contenuto e nella dimensione.
La creazione di una oggetto String può essere esplicita:
String S= new String(“parola”);
oppure implicita (caso più comune)
String S = “parola”;
Se proviamo a modificare una stringa, Java consente di farlo ma,
dietro le quinte, crea una nuova stringa con le modifiche richieste e
aggiorna il reference di quella originale
58. La classe Object
La classe Object è la classe padre di tutte le
classi, assegnata implicitamente dal compilatore.
Ciò fa si che tutte le proprietà e i metodi di Object
siano sempre disponibili in qualsiasi classe
Es: hashCode(), equal(), lenght
59. Le stringhe alfanumeriche (2)
Come tutti i Tipi, anche String ha una propria serie di
metodi: (prendiamo come riferimento “parola”)
length(): ritorna la lunghezza della stringa
Es: int len= s.length(); // len== 6
charAt(int i): ritorna il carattere in posizione i-esima
Es:char c=s.charAt(0) // c ==“p”
indexOf(char c): ritorna l‟indice della prima occorrenza del
carattere indicato
Es: inti=s.indexOf(„o‟) // i == 3
substring(int da,inta): ritorna una sottostringa
Es: String sub = s.substring(2,4) // sub==“ro”
60. Le stringhe alfanumeriche (3)
E’ possibile concatenare stringhe tramite l‟operatore
String s = “Prova” + “di” + “ concatenazione”;
System.out.println(s);
produrrà come output: “prova di concatenazione”
61. Array (1)
Molto spesso nei programmi si ha l'esigenza di
manipolare un gruppo di variabili dello stesso tipo
che contengono valori tra loro correlati.
Un array è uno strumento concettualmente simile ad
una tabella, che accomuna sotto un unico nome un
insieme di variabili dello stesso tipo:
int[] temp = new int[144];
Nel prosieguo utilizzeremo come sinonimi il termine “array” e
“vettore”
62. Array, dichiarazione (2)
Esattamente come per le variabili semplici dobbiamo
indicare un tipo ed un nome, con la differenza che, dopo
aver specificato il tipo, è necessario postporre una
coppiadi parentesi quadre.
int[] vettoreDiInteri;
La variabile “vettoreDiInteri” appena dichiarata non è
un vettore, ma solamente un reference ad un vettore
63. Array, assegnamento(3)
Per creare un vettore dobbiamo ricorrere alla parola riservata
“new”,
vettoreDiInteri = new int[10];
Il valore specificato tra parentesi quadre è la dimensione del
vettore.
E’ fondamentale evidenziare che un vettore è un oggetto di
memoria composto da un certo numero di elementi, ognuno dei
quali può contenere un valore
64. Array, dereferenziazione (4)
La dereferenziazione è un'operazione in cui creiamo una
variabile reference che punta ad un array già esistente
int[] vettoreDiInteri2;
vettoreDiInteri2 = vettoreDiInteri;
Le modifiche apportate all’oggetto si riflettono anche sull’altro,
quindi per creare veramente un nuovo array occorre copiare il
contenuto in un nuovo array
65. Array, popolamento ed inizializzazione(5)
Per assegnare un valore al vettore occorrerà specificare la posizione del
nuovo valore: vettoreDiInteri[1] = 10;
Teniamo presente che l’indice parte da 0 e non da 1!
Un vettore può essere inizializzato con una serie di valori, in
modo simile a come si può fare con le variabili.
L'istruzione:
int[] vettore = {10,12,14,16,18};
equivale alla sequenza:
int[] vettore = new int[5];
vettore[0] = 10;
vettore[1] = 12;
vettore[2] = 14;
vettore[3] = 16;
vettore[4] = 18;
66. Array, array bi e multi dimensionali(6)
Il linguaggio Java consente di creare array bi-dimensionali, raticamente
una matrice.
int i[][] = new int[10][15];
Un Array multidimensionale può essere inizializzato con una serie di valori,
in modo simile a come si può fare con gli Array semplici.
int[] vettore = { { 10,12,14},{16,18},{20,22,24,26}};
Il lignaggio permette inoltre di definire vettori con un numero qualunque di
dimensioni:
int v1[][][] = new int[10][15][5];
int v2[][][][] = new int[10][15][12][5];
ma di difficile lettura ed utilizzo.
E’ consigliabili limitarsi agli array lineari o alle matrici.
67. Array, array non rettangolari (6)
Java, infine, permette di definire array non rettangolari
int tabella[][] = new int[5][];
tabella[0] = new int[3];
tabella[1] = new int[2];
tabella[2] = new int[5];
tabella[3] = new int[2];
tabella[4] = new int[6];
68. Enumeratori
A partire da Java 5 è possibile definire una variabile con un numero
predefinito di valori, sia come variabile nella classe e sia come classe
esterna. enum Size { SMALL, BIG;}
Caratteristiche:
•Hanno modificatori: public static final
•Ereditano metodi:
• public static MyEnum valueOf(String name)
• public static MyEnum[] values()
70. Costrutti decisionali
•if-else : verificano diverse espressioni e quando viene
incontrata l'espressione che restituisce true viene eseguito un
determinato pezzo di codice.
•switch-case: viene esaminata UNA SOLA espressione, però
a seconda del suo risultato cambia il pezzo di codice che verrà
eseguito.
71. Costrutti decisionali ed iterativi
Un costrutto decisionale permette di vincolare l'esecuzione
di un'istruzione (o di un blocco di istruzioni) ad una
condizione booleana:
•condizione booleana è un'espressione della quale si
può dire se sia vera o falsa
• blocco di istruzioni è un insieme di istruzioni
racchiuso tra parentesi graffe, che vengono trattate dal
compilatore Java come se fossero un'istruzione unica
72. Costrutti decisionali, if – else (1)
Il costrutto condizionale più usato in Java è l'if, che può essere
usato nelle due varianti con o senza else
if ( condizioneBooleana )
istruzione;
La variante con l'else ha una forma del tipo
if ( condizioneBooleana )
istruzione1;
else
istruzione2;
73. Costrutti decisionali, if – else (2)
Se vogliamo che venga eseguita più di una istruzione
dobbiamo ricorrere ad un blocco:
if ( condizioneBooleana ) {
istruzione1a;
istruzione2a;
istruzione3a;
}
else {
istruzione1b;
istruzione2b;
istruzione3b;
}
74. Costrutti decisionali, if – else (3)
Il costrutto if può comparire anche all'interno di un altro costrutto
if, creando strutture nidificate anche molto complesse:
if( x >= 0 )
if( x <= 10 )
System.out.println("x compreso 0 e 10");
Se a questo punto inserisco un else dopo queste istruzioni.
if( x >= 0 )
if( x <= 10 )
System.out.println("x è compreso tra 0 e 10");
else
System.out.println("x è maggiore di 10");
A quale dei due if l‟istruzione else farà riferimento?
75. Costrutti decisionali, if – else (4)
Se ora aggiungiamo un else a quale if si riferisce?
if( x >= 0 )
if( x <= 10 )
System.out.println("x compreso 0 e 10");
else
System.out.println("x maggiore di 10");
else
System.out.println("x minore di 0");
Se volessimo forzare un solo else a far riferimento ad un if esterno?
76. Costrutti decisionali, if – else (5)
Per creare un blocco di istruzioni
if( x >= 0 )
{
if( x <= 10 )
System.out.println("x compreso 0 e 10");
}
else
System.out.println("x è minore di 0");
77. Costrutti decisionali, if – else annidati
E' buona norma di programmazione evitare di ricorrere
pesantemente alla nidificazione di istruzioni if, data la
confusione che spesso ne segue.
if( x >= 0 )
if( x <= 10 )
System.out.println("x compreso 0 e 10");
può tranquillamente essere sostituito dal seguente, in
tutto equivalente:
if( x >= 0 && x <= 10 )
System.out.println("x compreso 0 e 10");
78. Costrutti decisionali, if – else nidificati
E’ buona norma di programmazione evitare di
ricorrere pesantemente alla nidificazione di
istruzioni if, data la confusione che spesso ne
segue.
if( x >= 0 )
if( x <= 10 )
System.out.println("x compreso 0 e 10");
può tranquillamente essere sostituito dal seguente,
in tutto equivalente:
if( x >= 0 && x <= 10 )
System.out.println("x compreso 0 e 10");
79. Costrutti decisionali, if – else concatenati
Una combinazione condizionale si ha quando si fa
seguire ad un else una if.
if( x <= 0 )
System.out.println("x <= 0");
else if( x <= 10)
System.out.println("x > 0 e <= 10");
else if ( x <= 20)
System.out.println("x > 10 <= 20");
else
System.out.println("x è maggiore di 20");
Si noti che in questo caso l'ultimo else comprende
tutti i casi non considerati dalle precedenti istruzioni.
80. Costrutti decisionali, Espressioni condizionali
L'operatore “?”può essere usato all'interno di
espressioni matematiche, dove una delle sotto
espressioni sia vincolata ad una particolare
condizione booleana.
espressioneBooleana ? espressione1 : espressione2;
Esempio:
y = x < 0 ? 1 : 2;
if (x < 0) y = 1;
else y=2;
81. Costrutti decisionali, switch – case (1)
Il costrutto switch permette di gestire tutte
quelle situazioni in cui dobbiamo prendere
scelte diverse a seconda del valore di
un'espressione
switch (espressione) {
case val1:
istruzione_na; break;
case val2:
istruzione_nb;break;
default:
istruzione_ndefault;break;
}
82. Costrutti decisionali, switch – case (2)
•L'espressione contenuta tra le parentesi dello switch
deve essere di tipo intero (int, byte, short o char);
•ogni istruzione case lavora su di un particolare valore, e
fornisce una sequenza di istruzioni da eseguire in quella
circostanza
•Tale sequenza termina usualmente con l'istruzione
break, che forza il computer a uscire dallo switch, senza
verificare i valori successivi.
•blocco di default, ovvero una sequenza di istruzioni da
eseguire se non si è verificato nessuno dei casi precedenti.
83. I Cicli iterativi
•I cicli vengono abitualmente utilizzati in tutti quei
casi in cui bisogna eseguire delle attività ripetitive in
modo automatica.
•Abbiamo due tipi di cicli:
• cicli con contatore o Cicli For, utilizzati per
svolgere una data attività per un numero
determinato di volte
• i cicli condizionali o Cicli While, Do-While,
utilizzati per eseguire un'attività fino a quando una
data condizione viene soddisfatta
84. I Cicli iterativi, istruzioni while
La struttura generale del while è
while(condizioneBooleana) {
ISTRUZIONE1;
ISTRUZIONE2;
....
}
Se si desidera che un ciclo venga ripetuto all'infinito, è
sufficiente specificare una condizione sempre vera, tipo
while(0 == 0) { while(true) {
ISTRUZIONE1; ISTRUZIONE1;
} }
Se si desidera che il i = 0;
ciclo venga ripetuto un while(i<=100) {
ISTRUZIONI DA RIPETERE
numero prefissato di
i = i + 1;
volte }
85. I Cicli iterativi, do-while
•Dall’istruzione do-while a differenza della precedente,
controlla il valore della espressione booleana alla fine
del blocco di istruzioni. In questo caso quindi il blocco di
istruzioni verrà eseguito sicuramente almeno una volta.
La sintassi di do-while è la seguente
do {
istruzione;
}
while (espressione_booleana) {
istruzione;
};
86. I Cicli iterativi, for (1)
per effettuare un ciclo di 10 iterazioni utilizzando il ciclo while,
dovremmo scrivere qualcosa del tipo:
i=0;
while(i<10) {
faiQualcosa();
i++;
}
tramite il costrutto for è possibile ottenere lo stesso risultato in
maniera decisamente più
for(init_statement ; conditional_expr ; iteration_stmt)
{
istruzione
}
87. I Cicli iterativi, for (2)
•init_statement, rappresenta l‟inizializzazione della
variabile per il controllo del ciclo
•conditional_expr, l’espressione condizionale
•iteration_stmt l’aggiornamento della variabile di controllo
La situazione presentata precedentemente può essere risolto utilizzando
il ciclo for in questo modo:
for (int i=0 ; i<10 ; i++)
faiQualcosa();
88. I Cicli iterativi, foreach (1)
Per semplificare il ciclo for, in java 6 è stato introdotto
un ciclo specializzato che consente di ciclare su array e
collection.
for(declaration : expression)
•declaration: variabile compatibile con il tipo di elementi della collezione
•expression: collezione di elementi che può essere un array o un metodo
che ritorna un array
89. I Cicli iterativi, foreach (2)
Differenze tra for e foreach:
int[] a = {1, 2, 3, 4};
for (int x = 0; x < a.length; x++) {
System.out.print(a[x]);
}
for (int n : a) {
System.out.print(n);
}
Utilizzo del for enhanced per array annidati:
int[][] twoDee = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
for (int[] x : twoDee) {
for (int y : x) {
System.out.println(y);
}}
91. Collezioni
Spesso si rende necessario raggruppare un insieme di oggetti e accedere ad essi
secondo regole particolari (per esempio uno Stack o una Coda). In tali strutture
dati gli Array possono non essere adeguati.
1. Soluzione 1: Realizzare una propria classe che, utilizzando internamente
gli array, fornisce i metodi di accesso opportuni
2. Soluzione 2: Utilizzare classi già pronte fornite da Java, scegliendo quella
più opportuna ai propri bisogni
Java fornisce un insieme molto ampio di classi (concrete) in grado di collezionare
oggetti fornendo un interfacce (estese dalle proprie classi) relative a Pile, Code,
Insiemi, Liste, Mappe, Insiemi ordinati ecc …
(JCF) Java Collections Framework
91
93. JCF (2)
• Collection
• E’ in sostanza la classe base da cui derivano le specifiche tipologie di collezioni. Tra i
suoi metodi primari troviamo:
• boolean add(Object e)
• void clear()
• boolean contains(Object o)
• Iterator iterator()
• boolean remove(Object o) int size()
• List
• Una collezione ordinata di elemente (anche nota come sequeza) in cui l’utente ha una
precisa conoscenza di dove l’elemento (E) viene inserito:
• E get(int index)
• E set(int index, E element)
• Set
• Collezione che non ammette valori duplicati
• SortedSet
• Collezione che contiene elementi ordinati
94. Collezioni… di quali oggetti?
Tutti gli oggetti in java estendono da Object
E’ corretto scrivere: Object o=new Integer(10);
Le collection di java gestiscono elementi di tipo Object
Esse possono contenere elementi di tipo object
quindi un qualunque oggetto java può essere aggiunto in una collezione
NB: Gli oggetti vengono ritornati come Object e non del loro tipo specifico
ArrayList a=new ArrayList();
a.add(new Integer(10));//aggiungo un intero
Object elem=a.get(0); //oggetto di tipo Object
Per ottenere il tipo originario è necessario il cast esplicito
Integer i=(Integer) a.get(0);//cast esplicito
95. La Collection ArrayList
public class ArrayList extends …
boolean add(Object e)
Aggiunge l’oggetto alla fine della lista
void add(int index, Object element)
Inserisce l’oggetto nella posizione specificata
Object get(int index)
Ritorna l’oggetto presente nella posizione specificata
Object set(int index, Object element)
Sositutisce l’oggetto nella posizione specificata con quello indicato
void clear()
Svuota la lista
Iterator iterator()
Ritorna un iteratore per ciclare sulla lista
int size()
Ritorna il numero di elementi presenti nella lista
96. Iteratori
Si tratta di un operatore «agnostico» che permette di scorrere gli elementi di una collezione
indipendentemente dalla loro disposizione
• Il metodo iterator() è disponibile in tutte classi che estendono da Collection
Iterator
boolean hasNext()
Ritorna true se esiste un altro elemento
Object next()
Ritorna l’elemento successivo
void remove()
Rimuove dalla collezione l’ultimo elemento iterato
97. Esempi
public static int somma(ArrayList a){
int somma=0;
for (int i=0;i<a.size();i++){
Integer elem=(Integer)a.get(i)
somma=somma+elem.intValue();
}
return somma;
}
public static int somma(ArrayList a){
int somma=0;
Iterator i=a.iterator();
while (i.hasNext()){
Integer val=(Integer)i.next();
somma=somma+val.intValue();
}
return somma;
}
98. JCF (3)
public interface Collection
boolean add(Object e)
Appends the specified element to the end of this list.
void add(int index, Object element)
Inserts the specified element at the specified position in this list.
void clear()
Removes all of the elements from this list.
Iterator iterator()
Returns an iterator over the elements in this list in proper sequence.
int size()
Returns the number of elements in this list.
boolean isEmpty()
Returns true if this collection contains no elements.
… altri metodi
99. JCF (4)
public interface List extends Collection
Ereditate da Collection
boolean add(Object e)
void add(int index, Object element)
void clear()
Iterator iterator()
int size()
boolean isEmpty()
E get(int index)
Returns the element at the specified position in this list.
E remove(int index)
Removes the element at the specified position in this list (optional operation).
E set(int index, E element)
Replaces the element at the specified position in this list with the specified element (optional
operation).
… altri metodi
100. JCF (5)
• public class ArrayList …implements List public class Vector …implements List
• Ereditate da List Ereditate da List
• boolean add(Object e) boolean add(Object e)
• void add(int index, Object element) void add(int index, Object element)
• void clear() void clear()
• Iterator iterator() Iterator iterator()
• int size() int size()
• boolean isEmpty() boolean isEmpty()
• E get(int index) E get(int index)
• E remove(int index) E remove(int index)
• E set(int index, E element) E set(int index, E element)
• … altri metodi … altri metodi
Analogo ad ArrayList ma l’implementazione è
thread-safe ed è in genere più lenta
101. JCF (6)
public class LinkedList …implements List
Ereditate da List
boolean add(Object e)
void add(int index, Object element)
void clear()
Iterator iterator()
int size()
boolean isEmpty()
E get(int index)
E remove(int index)
E set(int index, E element)
E getFirst()
Returns the first element in this list.
E getLast()
Returns the last element in this list.
… altri metodi
NB: L’implementazione di get e set hanno costo O(n)
102. Il problema della mancata tipizzazione
Il problema della mancata tipizzazione (alias utilizzo di Object)
1. Necessità di ricorrere al cast degli elementi anche quando il tipo di elementi è noto
ArrayList a=new ArrayList();
a.add(new Integer(10));
...
Integer i=(Integer)a.get(0);
2. Possibili cast degli elementi a tipi non corretti
ArrayList a=new ArrayList();
a.add(new Integer(10));
...
String i=(String)a.get(0);//eccezione!!!
3. Nessun controllo sui tipi di dati inseriti all’interno di un vettore
ArrayList a=new ArrayList();
a.add(new Integer(10));
...
a.add(new String(“paperino”));//?
Integer i=(Integer)a.get(0);//OK
Integer j=(Integer)a.get(1);//cast exception
4. Poca chiarezza sul tipo di dati trattati
public static ArrayList calcolaQualcosa() //che tipi contiene?
In tutti i casi, il codice risulta sintatticamente corretto e non viene segnalato alcun errore
dal compilatore. L’errore viene scoperto solo a Runtime!
103. I Generics
Programmazione generica: creazione di costrutti di programmazione che possano essere utilizzati con tipi di dati diversi.
In Java si può raggiungere l’obiettivo della programmazione generica usando l’ereditarietà oppure le variabili di tipo.
Esempio: ArrayList di Java ArrayList<String>
Classe generica: è stata dichiarata usando una variabile di tipo E.
La variabile di tipo rappresenta il tipo degli elementi:
public class ArrayList<E>
// si può usare "ElementType" invece di E
{
public ArrayList() { . . . }
public void add(E element) { . . . }
...
}
Le variabili di tipo possono essere sostituite, all’atto della creazione di esemplari, con nomi di classe o di interfacce
ArrayList<String>
ArrayList<MyClass>
Non si può usare come sostituto uno degli otto tipi di dati primitivi
ArrayList<double> // Sbagliato!
Usate un esemplare di ArrayList<Double>
105. I Generics (2)
• Il tipo di dato indicato va a sostituire la variabile di tipo utilizzata nella definizione
dell’interfaccia o della classe generica
Esempio: nel metodo add di un oggetto di tipo ArrayList<String> la variabile di
tipo E viene sostituita dal tipo String
• public void add(String element)
• Le variabili tipizzate rendono più sicuro e di più facile comprensione il codice generico.
E’ impossibile aggiungere un oggetto di tipo Integer ad un esemplare di
ArrayList<String>
È invece possibile aggiungere un oggetto di tipo Integer ad un esemplare di ArrayList
(senza generics) che sia stato creato con l’intenzione di usarlo per contenere stringhe
106. I Generics (3)
ArrayList<String> a1 = new ArrayList<String>();
Integer numero=new Integer(30);
// Dovrebbe contenere oggetti di tipo String
ArrayList a2 = new LinkedList();
// errore di compilazione
a1.add(numero);
// errore non individuato dal compilatore
a2.add(numero);
//errore di esecuzione
String account = (String) a2.get(0);
107. I Generics (4)
ArrayList<E>
boolean add(E e)
void add(int index, E element)
E get(int index)
public static int somma(ArrayList<Integer> a)
E set(int index, E element) {
void clear() int somma=0;
for (int i=0;i<a.size();i++){
Iterator<E> iterator()
Integer elem=a.get(i)
int size() somma=somma+elem.intValue();
}
return somma;
Iterator<E> }
boolean hasNext()
E next()
void remove()
110. I membri dei Package
I Package permettono sostanzialmente di organizzare il
codice in una sorta di contenitori in cui vengono inglobate
classi omogenee:
• caratteristiche in comune (java.io)
• appartengono allo stesso progetto (it.fastweb.crm.om.)
• vengono prodotte dalla stessa societa (com.cedati)
111. I membri dei Package
I packages sono identificati dall'istruzione package,
che deve apparire come la prima istruzione nel file del
codice sorgente.
package mioPackage;
public class MiaClasse {
...........
}
112. Uso delle classi del Package (1)
Un membro pubblico (classe, interfaccia, ecc) di un package può essere
utilizzato in tre modi diversi:
1. attraverso il suo nome completo
2. importandolo
3. importando l‟intero package a cui il membro appartiene
113. Uso delle classi del Package, nome
completo (2)
Indichiamo:
•nome del package
•l’operatore: che ci permette di entrare internamente nel package
•il nome della classe
public class Classe {
mioPackage. MiaClasse fg;
}
114. Uso delle classi del Package,
nome della singola classe (3)
Indichiamo:
•import seguito del nome del package seguito dalla classe
•dichiariamo l‟oggetto fg nel modo classico
import mioPackage.MiaClasse;
public class Classe {
MiaClasse fg;
}
115. Uso delle classi del Package, import dell’intero
package (3)
Indichiamo:
•import di tutte le classi del package attraverso il simbolo “*”
•dichiariamo l‟oggetto fg
import mioPackage.*;
public class Classe {
MiaClasse fg;
}
116. Salvare e compilare una classe di un package
• Una classe appartenente ad un package deve essere salvata all‟interno dell‟albero che
viene definito dal path del package:
• Esempio:
package mioPackage.mioEsempio
class MiaCLasse {...}
• la classe MiaClasse.java deve essere salvata nelle cartelle mioPackagemioEsempio
c:mioPackagemioEsempio>dir
MiaClasse.java
c:mioPackagemioEsempio> javac MiaClasse.java
c:mioPackagemioEsempio>dir
MiaClasse.java
MiaClasse.class
117. Eseguire una classe del package
• Per eseguire una classe contenuta in un package occorre lanciare la classe
(che contiene il main) dall’esterno della prima cartella che delimita il
package
• Esempio:
C:mioPackagemioEsempio>dir
MiaClasse.java
MiaClasse.class
c:>java mioPackage.mioEsempio.MiaClasse
118. Import e Import statici
• Mentre l‟istruzione import consente di importare le
classi o interfacce, l‟import statico consente di importare
proprietà static di una classe:
import static java.lang.System.out;
public class ProvaImportStatic {
public static void main(String[] args) {
out.println("Hello");
}
}
119. Documentazione e javadoc
• E‟ possibile generare direttamente dai sorgenti java la
documentazione dello sviluppo.
• I commenti al codice vengono inseriti nella
documentazione per essere leggibili dal browser.
• Per fare questo si utilizza l‟utility presente nel JDK dal
nome “javadoc”
120. Documentazione e javadoc
• Partiamo da una classe appositamente
commentata:
/** Classe di Prova **/
public class Prova {
/** Proprietà privata x **/
private int x = 0;
/** Descrione del metodo **/
public String metodo(int t) throws Exception {
return "";
}
}
122. Annotazioni (1)
•Le annotazioni possono essere create per “annotare” degli aspetti
importanti del programma in modo da rendere il codice più leggibile.
•Vengono usate spesso per passare delle note al compilatore in modo
tale che questi possa svolgere il proprio compito in un modo più
efficiente.
“annotazione” nel codice:
public class MiaProva {
@Deprecated
public void metodoConNotazione(){}
}
public class Avvio{
public static void main(String [] args ){
new MiaProva().metodoConNotazione();
}
}
124. Annotazioni (3)
Creiamo una nostra “annotazione” ed usiamola nel
codice:
public @interface ProvaAnnotazione {
String nome();
}
public class MiaProva {
@ProvaAnnotazione(nome="primaAnnotazione")
public void metodoConNotazione(){}
}
126. Meccanismo vincolante delle eccezioni
• Una eccezione è un evento che si verifica durante l‟esecuzione di un
programma e che ne impedisce la normale prosecuzione a causa di
errori hardware o semplici errori di programmazione.
• Il sistema runtime, per la gestione dell‟eccezione, cerca“candidati” a
partire dal metodo nel quale l‟eccezione è stata“sollevata”,
proseguendo eventualmente lungo lo stack delle chiamate, finché
non trova un metodo contenente un gestore(exception handler)
opportuno.
• Se non viene trovato nessun exception handler adatto alla gestione
di un‟eccezione, il programma termina.
127. Meccanismo vincolante delle eccezioni
Una eccezione potrà essere:
• gestita attraverso gli exception handler
• propagata lungo lo stack delle chiamate dei metodi
Un exception handler è composto da tre parti principali:
• un blocco try
• uno o più blocchi catch (opzionali)
• un blocco finally
Nel caso si decida di propagare una eccezione lungo lo stack delle chiamate occorre
utilizzare la parola chiave throws al metodo.
• La propagazione dell‟eccezione consente ad un metodo di non doversi preoccupare di
gestirlo.
• Se i metodi chiamanti non hanno previsto la gestione dell‟errore, allora il programma
si interromperà
128. Le eccezioni di RunTime
• Alcune eccezioni possono verificarsi a causa di errori di coloro che
utilizzano il programma e non ad opera di coloro che l‟hanno
realizzato.
• Possono sempre presentarsi ed il programmatore può
semplicemente provare a gestirle ma non può impedirle.
129. Eccezioni personalizzate
• La creazione di eccezioni da parte del programmatore nasce dalla
necessità di gestire efficacemente situazioni di errore (o comunque
anomale) non previste dalle eccezioni standard di Java ma che si
possono comunque verificare durante l‟esecuzione del programma che
si sta progettando
• Esempio:
public class ElementoInesistenteException extends Exception {
public String nomeElemento;
public ElementoInesistenteException(String nome) {
super("Non esiste alcun elemento'" + nome);
nomeElemento = nome;
}
}
131. Il package java.lang
• Il package java.lang è importato di default in quanto
contiene la struttura di base per la creazione di una
classe java.
• E‟ composto da:
interfacce: Cloneable, Comparable, Runnable
classi: Wrapper( Byte, Short, Integer, Long, Float, Double,
Boolean, Character, Void ) String, System, Thread, Object,
Runtime, SecurityManager,
eccezioni: Throwable
132. Il package java.util
• Il package java.util contiene delle classi di utility che
servono al programmatore per implementare i propri
algoritmi.
• Per esempio: liste ordinate/casuali con valori
unici/duplicati, tabelle di elementi, calendari,
comparatori di elementi, gestori della localizzazione
geografica
• interfacce/classi: List, Set, Map, Collection, Iterator,
Enumeration, Calendar, Comparator, Local
133. Il package java.text
• Il package java.text permette di convertire oggetti in
testo e viceversa.
• Per esempio: DateFormat, DecimalFormat,
MessageFormat, NumberFormat,