ArrayList e Generics - e-Learning

08/06/2014
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java
ArrayList e Generics
Daniela Micucci
[email protected]
ARRAYLIST
Programmazione con Java ‐ ArrayList e Generics
2
1
08/06/2014
La classe ArrayList
• Fa parte delle librerie standard di Java
• In generale, un ArrayList assolve lo stesso compito di un array, ad eccezione del fatto che un oggetto ArrayList può cambiare lunghezza mentre il programma è in esecuzione
• La classe ArrayList è implementata utilizzando un array come una variabile di istanza privata – Quando l’array è pieno, viene creato un nuovo array di dimensione più grande e vengono spostati al suo interno gli elementi
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
3
La classe ArrayList
• Realizza una lista di elementi (oggetti)
• Gli elementi possono essere aggiunti:
– Alla fine
– All’inizio
– Tra altri elementi
• È possibile editare, cancellare, accedere e contrare gli elementi all’interni della lista
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
4
2
08/06/2014
Creare ArrayList
• Al fine di utilizzare la classe ArrayList, occorre importarla dal package java.util
• L’utilizzo è lo stesso di una qualsiasi altra classe, ad eccezione del fatto che va specificato il tipo base come segue:
ArrayList<TipoBase> objName = new ArrayList<TipoBase>();
• In fase di instanziazione, il tipo base verrà sostituito da un tipo reference (o tipo classe) che specificherà il tipo di elementi che la lista conterrà
import java.util.ArrayList;
public class Demo01 {
public static void main(String[] args) {
//Capacità iniziale pari a 10 elementi
ArrayList<String> lista = new ArrayList<String>();
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
5
Creare ArrayList
• Può essere specificata una capacità iniziale nel momento della creazione
ArrayList<TipoBase> objName = new ArrayList<TipoBase>(cap);
• Anche se si specifica la capacità iniziale, la lista può crescere di dimensione dinamicamente
import java.util.ArrayList;
public class Demo01 {
public static void main(String[] args) {
//Capacità iniziale pari a 20 elementi
ArrayList<String> lista = new ArrayList<String>(20);
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
6
3
08/06/2014
Usare metodi di ArrayList
• Per poter inserire/eliminare/manipolare elementi di una lista occorre utilizzare i metodi che ArrayList mette a disposizione
– A differenza degli array che permettono solo:
• Uso delle []
• Variabile length
• Aggiungere elementi:
In ultima posizione
public boolean add(TipoBase nuovoElemento)
public void add(int index, TipoBase nuovoElemento)
In posizione specificata da index.
0<= index <= indice dell’ultimo elemento +1
• Modificare elementi:
In posizione specificata da index.
0<= index <= indice dell’ultimo elemento
public void set(int index, TipoBase nuovoElemento)
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
7
Esempio 1
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<String>();
lista.add("Mele");
lista.add("Pere");
lista.add("Uova");
lista.add(2, "Insalata");
System.out.println(lista);
}
}
Output:
[Mele, Pere, Insalata, Uova]
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
8
4
08/06/2014
Esempio 2
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<String>();
lista.add("Mele");
lista.add("Pere");
lista.add("Uova");
lista.add(2, "Insalata");
System.out.println(lista);
lista.set(0, "Albicocche");
System.out.println(lista);
}
}
Output:
[Mele, Pere, Insalata, Uova]
[Albicocche, Pere, Insalata, Uova]
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
9
Accedere in lettura e rimozione
• Accedere a singoli elementi:
public TipoBase get(int index)
…
ArrayList<String> lista = new ArrayList<String>();
lista.add("Mele");
String elemento = lista.get(0);
…
In posizione specificata da index.
0<= index <= indice dell’ultimo elemento
• Rimuovere elementi:
public TipoBase remove(int index)
…
ArrayList<String> lista = new ArrayList<String>();
lista.add("Mele");
String elemento = lista.remove(0);
…
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
10
5
08/06/2014
Numero elementi in un ArrayList
• Il metodo size è utilizzato per determinare il numero di elementi all’interno dell’ArrayList
public int size()
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<String>();
lista.add("Mele");
lista.add("Pere");
int numElem = lista.size();
System.out.println(numElem);
}
}
Output:
2
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
11
Altri metodi
• Rimuovere tutti gli elementi
public void clear()
• Verificare se la collezione è vuota
public boolean isEmpty()
• Verificare se la collezione contiene un certo elemento
public boolean contains(Object elem)
• … consultare la documentazione!
– http://docs.oracle.com/javase/
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
12
6
08/06/2014
Metodo contains
• Si basa sull’equals
• Esempio:
– Creare un ArrayList di String e un ArrayList di Persona
– Inserire rispettivamente la String «Ciao» e la Persona con nome Mario e età 21
– Verificare se il primo array contiene la String «Ciao» e il secondo la Persona Mario con età 21
– Codificare equals in Persona e riprovare
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
13
Scorrere un ArrayList
• La classe ArrayList è un esempio di collection class
(letteralmente classe collezione)
• Con la versione 5.0, Java ha aggiunto un nuovo tipo di loop
chiamato for‐each o enhanced for
• Questo ciclo è stato progettato per ciclare tutti gli elementi di una collezione (come appunto un ArrayList)
• Sintassi:
for (TipoBase_Array_List var : ArrayList_Obj) {
//istruzioni
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
14
7
08/06/2014
Esempio for-each
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<String>();
lista.add("Mele");
lista.add("Pere");
lista.add("Uova");
lista.add(2, "Insalata");
for (String elemento : lista) {
System.out.println(elemento);
}
}
}
Output:
Mele
Pere
Insalata
Uova
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
15
Esempi pratico: Insieme di stringhe
• Si implementi il concetto di insieme di stringhe che supporti le tipiche operazioni fra insiemi:
– Aggiunta di elementi
– Appartenenza di un elemento – Unione e intersezione di un insieme rispetto ad un altro insieme, – Calcolo della cardinalità
– Verifica se l’insieme è vuoto InsiemeDiStringhe
-
elementi :ArrayList<String>
+
+
+
+
+
+
+
InsiemeDiStringhe()
aggiungi(elemento :String) :void
appartiene(daVerificare :String) :boolean
cardinalita() :int
vuoto() :boolean
unisciCon(altroInsieme :InsiemeDiStringhe) :void
intersecaCon(altroInsieme :InsiemeDiStringhe) :void
• Si realizzi un caso di test che – crea l’insieme {«mela», «pera», «banana»} e l’insieme {«papaia», «banana», «fragola»} – faccia l’unione del primo con il secondo e verifichi che il primo insieme non è vuoto ha cardinalità 5
– faccia l’intersezione del primo con il secondo e verifichi che il primo insieme non è vuoto ha cardinalità 1
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
TestCase
InsiemeDiStringheTest
+
+
testUnione() :void
testIntersezione() :void
16
8
08/06/2014
Esercizio pratico: todo list
«interface»
ToDoList
+
+
+
+
+
+
+
+
• Versione array e versione ArrayList per l’associazione con Attivita
inserisciAttivita(Attivita) : void
rimuoviAttivita(Attivita) : void
sostituisciAttivita(Attivita, Attivita) : void
svuotaLista() : void
durataComplessivaAttivita() : int
durataComplessivaAttivitaSvolte() : int
durataComplessivaAttivitaDaSvolgere() : int
svolgiAttivita() : void
ToDoListArray
TestCase
TestToDoListArrayList
+
+
+
testSostituzione() : void
testRimozione() : void
testSvolgimento() : void
ToDoListArrayList
-
lista: Attivita ([])
-
lista: ArrayList<Attivita>
+
+
+
+
+
+
+
+
+
+
ToDoListArray()
inserisciAttivita(Attivita) : void
rimuoviAttivita(Attivita) : void
sostituisciAttivita(Attivita, Attivita) : void
svuotaLista() : void
durataComplessivaAttivita() : int
durataComplessivaAttivitaSvolte() : int
durataComplessivaAttivitaDaSvolgere() : int
svolgiAttivita() : void
toString() : String
+
+
+
+
+
+
+
+
+
+
ToDoListArrayList()
inserisciAttivita(Attivita) : void
rimuoviAttivita(Attivita) : void
sostituisciAttivita(Attivita, Attivita) : void
svuotaLista() : void
durataComplessivaAttivita() : int
durataComplessivaAttivitaSvolte() : int
durataComplessivaAttivitaDaSvolgere() : int
svolgiAttivita() : void
toString() : String
Attiv ita
-
descrizione: String
durataInMinuti: int
svolta: boolean
-lista
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐
-lista
+ Attivita(String, int)
* + getDescrizione() : String *
+ getDurataInMinuti() : int
+ isSvolta() : boolean
+ svolta() : void
ArrayList e Generics
+ toString() : String
+ equals(Object) : boolean
17
GENERICS
Programmazione con Java ‐ ArrayList e Generics
18
9
08/06/2014
Classi parametriche e Generici
• La classe ArrayList è una classe parametrica
– Ha un parametro, denominato tipo base che può essere sostituito da un qualsiasi tipo reference (tipo classe)
• A partire dalla versione 5.0 (Tiger), Java permette di definire classi con tipi parametrici
• Queste classi sono chiamate classi parametriche o definizioni
generiche o generici
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
19
Classi parametriche e Generici
• La classe ArrayList è una classe parametrica
– Ha un parametro, denominato tipo base che può essere sostituito da un qualsiasi tipo reference (tipo classe)
• A partire dalla versione 5.0 (Tiger), Java permette di definire classi con tipi parametrici
• Queste classi sono chiamate classi parametriche o definizioni
generiche o generici
• Esiste anche la versione non parametrica della classe ArrayList
– Che tipo di oggetti specifica di contenere?
– Come manipolo i tipi specifici?
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
20
10
08/06/2014
Perché i generici?
• Si supponga di voler definire una classe che modella una scatola in grado di contenere un oggetto che a priori non si sa cosa sia
• Con le conoscenze attuali:
public class ScatolaVersione1 {
private Object oggetto;
public void inserisci(Object oggetto) {
this.oggetto = oggetto;
}
public Object rimuovi(){
Object tmp = oggetto;
oggetto = null;
return tmp;
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
21
Perché i generici?
• Come recuperare un oggetto inserito nella scatola per poterlo manipolare correttamente? public class DemoScatolaVersione1 {
public static void main(String[] args) {
ScatolaVersione1 scatola1 = new ScatolaVersione1();
scatola1.inserisci(new Libro("Programmazione", 600));
Object elemento = scatola1.rimuovi();
if(elemento instanceof Libro){
Libro libro = (Libro)elemento;
System.out.println(libro.getNumeroPagine());
}
}
Obj ect
}
• … wow!
Software Architecture Lab
www.sal.disco.unimib.it
CDAudio
Libro
-
titolo: String
numeroPagine: int
+
+
+
Libro(titolo :String, numeroPagine :int)
getTitolo() : String
getNumeroPagine() : int
Programmazione con Java ‐ ArrayList e Generics
-
autore: String
titolo: String
numeroTracce: int
+
+
+
+
CDAudio(autore :String, titolo :String, numeroTracce :int)
setAutore(autore :String) : void
setTitolo(titolo :String) : void
setNumeroTracce(numeroTracce :int) : void
22
11
08/06/2014
Generici
• Classi e metodi possono specificare un tipo parametrico invece di un tipo ben specifico (classe o primitivo)
• Il tipo parametrico può essere sostituito con qualsiasi tipo classe
• Tradizionalmente viene utilizzata una singola lettera maiuscola per specificare il tipo parametrico
– In realtà è possibile utilizzare qualsiasi identificativo diverso dalle keyword del linguaggio
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
23
Generici
• Una definizione di classe con tipo parametro è memorizzata in un file e compilato come qualsiasi altra classe
• Una volta compilata, la classe può essere usata come qualsiasi altra classe
• La differenza sta solo nel fatto che va specificato il tipo classe prima di poter usare la classe parametrica
• Ciò lo si fa istanziando la classe generica:
ClasseParametrica<TipoClasseScelta> objName =
new ClasseParametrica<TipoClasseScelta>();
• Esempio:
ArrayList<String> objName = new ArrayList<String>();
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
24
12
08/06/2014
Definire una classe parametrica
• La classe Scatola rivista
public class ScatolaVersione2 <T> {
private T oggetto;
public void inserisci(T elemento){
this.oggetto = elemento;
}
1. Il tipo parametrico è specificato all’interno di <>
2. Va specificato subito dopo il nome della classe
3. Può essere utilizzato un identificativo a piacere
(ad esclusione delle keyword)
1. Il tipo parametrico è utilizzato all’interno
della classe come un qualsiasi altro tipo
(primitivo o classe)
public T rimuovi(){
T tmp = oggetto;
oggetto = null;
return tmp;
}
T
ScatolaVersione2
}
Software Architecture Lab
www.sal.disco.unimib.it
-
oggetto: T
+
+
+
+
ScatolaVersione2(elemento :T)
ScatolaVersione2()
inserisci(elemento :T) : void
rimuovi() : T
Programmazione con Java ‐ ArrayList e Generics
25
Usare una classe parametrica
public class DemoScatolaVersione2 {
public static void main(String[] args) {
ScatolaVersione1 scatola1 = new ScatolaVersione1();
scatola1.inserisci(new Libro("Programmazione", 600));
Object elemento = scatola1.rimuovi();
if(elemento instanceof Libro){
Libro libro = (Libro)elemento;
System.out.println(libro.getNumeroPagine());
}
//Con i Generics
ScatolaVersione2<Libro> scatola2 = new ScatolaVersione2<Libro>();
scatola2.inserisci(new Libro("Programmazione", 600));
Libro libro = scatola2.rimuovi();
System.out.println(libro.getNumeroPagine());
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
26
13
08/06/2014
Classe parametrica con costruttori
public class ScatolaVersione2 <T> {
private T oggetto;
public ScatolaVersione2(T elemento){
inserisci(elemento);
}
public ScatolaVersione2(){
this(null);
}
public void inserisci(T elemento){
this.oggetto = elemento;
}
public T rimuovi(){
T tmp = oggetto;
oggetto = null;
return tmp;
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
27
Convenzioni di naming
• I nomi per i tipi parametrici più usati sono:
– E ‐ Element • Usato in maniera estensiva dal Java Collection Framework
–
–
–
–
–
K ‐ Key
N ‐ Number
T ‐ Type
V ‐ Value
S,U,V etc. ‐ 2nd, 3rd, 4th types
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
28
14
08/06/2014
Pitfall #1
• Il costruttore di una classe parametrica non viene specificato mediante <>
public ScatolaVersione2(T elemento)
public ScatolaVersione2()
Ok!
public ScatolaVersione2<T>(T elemento)
public ScatolaVersione2<T>()
Ko!
• … anche se quando si istanzia una classe parametrica si usano le <>
Libro libro = new Libro(“Programmazione", 600);
ScatolaVersione2<Libro> scatola1 =
new ScatolaVersione2<Libro>(libro);
ScatolaVersione2<Libro> scatola2 =
new ScatolaVersione2<Libro>();
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
29
Pitfall #2
• Il tipo base non può essere sostituito con un tipo primitivo
• Però Java mette a disposizione per ogni tipo primitivo la classe corrispondente (chiamata wrapper)
• Un wrapper di tipo primitivo è un oggetto che incapsula un attributo di tipo primitivo:
– Mantiene il comportamento del tipo primitivo
– Permette di usarlo come un oggetto
Software Architecture Lab
www.sal.disco.unimib.it
Tipo primitivo
Classe
boolean
Boolean
char
Char
byte
Byte
short
Short
int
Integer
long
Long
float
Float
double
Double
Programmazione con Java ‐ ArrayList e Generics
30
15
08/06/2014
Classi wrapper: Boxing
• Il processo di conversione da tipo primitivo ad oggetto della corrispondente classe wrapper
• Si può pensare come ad una «scatola» in cui viene inserito un valore di tipo primitivo (boxing = inscatolamento)
• Fatto in maniera automatica da Java
Integer n = new Integer(42);
Double d = new Double(9.99);
Character c = new Character(‘z’);
Integer n = 42;
Double d = 9.99;
Character c = ‘z’;
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
31
Classi wrapper: Unboxing
• Il processo di conversione inverso – da oggetto a corrispondente tipo primitivo
• Fatto in maniera automatica da Java
– Esistono dei metodi opportuni
Integer n = new Integer(42);
int i = n;
int a = new Integer(42);
double d = new Double(9.99);
char c = new Character(‘z’);
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
32
16
08/06/2014
Pitfall #2: esempio
public class DemoScatolaVersione3 {
public static void main(String[] args) {
ScatolaVersione2<Integer> scatola = new ScatolaVersione2<Integer>();
scatola.inserisci(new Integer(4));
Integer i = scatola.rimuovi();
//inboxing aoutomatico
scatola.inserisci(4);
//outboxing aoutomatic
int x = scatola.rimuovi();
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
33
Pitfall #3
• A differenza di un tipo classe che può essere utilizzato sempre all’interno di una definizione di classe, il tipo parametrico ha alcune limitazioni
• In particolare, non può essere utilizzato con la new, i.e., per creare oggetti
T object = new T();
T[] a = new T[10];
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
34
17
08/06/2014
Pitfall #4
• Array definiti come segue sono illegali:
ScatolaVersione2<String>[] a =
new ScatolaVersione2<String>[10];
• Anche se sembra ragionevole, ciò non è permesso dal modo
con cui Java realizza i generici
Programmazione con Java ‐ ArrayList e Generics
Software Architecture Lab
www.sal.disco.unimib.it
35
Più tipi parametrici
• Una definizione di classe può avere un qualsiasi numero di tipi parametrici
public class CoppiaAssortita<T, E> {
private T primo;
private E secondo;
• I parametri sono elencati in parentesi angolari come unico tipo parametrico, ma sono separati da una virgola
public CoppiaAssortita(T primo, E secondo){
this.primo = primo;
this.secondo = secondo;
}
public void setPrimo(T primo){
this.primo = primo;
}
public void setSecondo(E secondo){
this.secondo = secondo;
}
T
E
CoppiaAssortita
-
primo: T
secondo: E
public T getPrimo(){
return primo;
}
+
+
+
+
+
CoppiaAssortita(primo :T, secondo :E)
setPrimo(primo :T) : void
setSecondo(secondo :E) : void
getPrimo() : T
getSecondo() : E
public E getSecondo(){
return secondo;
}
}
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
36
18
08/06/2014
Utilizzo di una classe con più tipi parametrici
public class DemoCoppiaAssortita {
public static void main(String[] args) {
CoppiaAssortita<Libro, Integer> ca1 =
new CoppiaAssortita<Libro, Integer> (new Libro("I pilastri della terra", 1000), 9);
Libro l = ca1.getPrimo();
int score = ca1.getSecondo();
System.out.println("Il libro " + l.getTitolo() +
" ha uno score pari a " + score);
}
}
Output:
Il libro I pilastri della terra ha uno score pari a 9
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
37
Pitfall #5
• Non è permesso definire classi generiche che specializzano Throwable o classi discendenti
– Eg. Exception, Error
• Ad esempio:
public class ProvaEccezione <T> extends Exception
• genererà un errore in compilazione
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
38
19
08/06/2014
Limitare i tipi parametrici
• A volte risulta utile limitare (bound) i tipi che possono essere utilizzati per attualizzare un tipo parametrico T
• Ad esempio, per assicurare che i tipi classe che possono essere utilizzati siano di tipo VeicoloMotorizzato
public class Silos <T extends VeicoloMotorizzato> {
//...
}
T:extends VeicoloMotorizzato
«interface»
VeicoloMotorizzato
public class DemoSilos {
+
+
+
public static void main(String[] args) {
+
Silos<Auto> silos1 = new Silos<Auto>();
Silos<Camper> silos2 = new Silos<Camper>();
}
Silos
accendi() : void
spegni() : void
frena() : void
accelera() : void
+
entrata(T) : void
}
Camper
+
+
+
+
Software Architecture Lab
www.sal.disco.unimib.it
accendi() : void
spegni() : void
frena() : void
accelera() : void
Auto
+
+
+
+
accendi() : void
spegni() : void
frena() : void
accelera() : void
Programmazione con Java ‐ ArrayList e Generics
39
Limitare i tipi parametrici
• Ogni tentativo di inserire un tipo che non specializza la classe VeicoloMotorizzato risulterà in un errore in compilazione:
Silos<Libro> silos1 = new Silos<Libro>();
• Un bound su un tipo può essere specificato mediante un nome di classe (o di interfaccia)
• Solo le classi discendenti di quella bounding possono essere specificate come tipo
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
40
20
08/06/2014
Limitare i tipi parametrici
• Una espressione di bounding può contenere una o più interfacce, ma solo una classe
• La sintassi è la seguente
public class ProvaSimple <T extends ClassC & InterfaceA & InterfaceB>
• Se c’è più di un tipo parametrico
public class ProvaSimple <T extends ClassC & InterfaceA & InterfaceB,
E extends ClassD>
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
41
Interface generiche
• Una interface può avere uno o più tipi parametrici
• I dettagli e le notazioni sono analoghe a quelle viste per le classi
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
42
21
08/06/2014
Ereditarietà con i generici
• Una classe generica può essere definita come derivata di
– Una classe ordinaria
– Un’altra classe generica
• Date due classi Auto e CityCar e una classe generica Silos, non sussiste alcuna relazione tra Silos<Auto> e Silos<CityCar> anche se CityCar è una specializzazione di Auto
Programmazione con Java ‐ ArrayList e Generics
Software Architecture Lab
www.sal.disco.unimib.it
43
Ultima nota
• Una volta specificato il tipo classe, è possibile utilizzare oggetti istanziati a partire da quella classe e sottoclasse
T:extends VeicoloMotorizzato
«interface»
VeicoloMotorizzato
+
+
+
+
accendi() : void
spegni() : void
frena() : void
accelera() : void
Camper
+
+
+
+
Silos
accendi() : void
spegni() : void
frena() : void
accelera() : void
+
Auto
+
+
+
+
accendi() : void
spegni() : void
frena() : void
accelera() : void
CityCar
Software Architecture Lab
www.sal.disco.unimib.it
entrata(T) : void
public class DemoSilos {
public static void main(String[] args) {
Silos<VeicoloMotorizzato> silos3 =
new Silos<VeicoloMotorizzato>();
silos3.entrata(new Auto());
silos3.entrata(new CityCar());
silos3.entrata(new Camper());
}
}
Programmazione con Java ‐ ArrayList e Generics
44
22
08/06/2014
Sempre inerente all’ultima nota
• Attenzione però a …
import java.util.ArrayList;
import java.util.List;
public class Prova {
public static void main(String[] args) {
//Vale tutto il principio dei tipi e sottotipi
//List è una superclasse di ArrayList
List<Number> numbers = new ArrayList<Number>();
//2 è un Integer che è una sottolcasse di Number
numbers.add(2); //Integer
//3.14d è un Double che è una sottolcasse di Number
numbers.add(3.14d); //Double
/*ATTENZIONE pero' che
* che ArrayList<Integer> NON E' UN SOTTOTIPO di ArrayList<Number>
* (e tanto meno List<Integer> di ArrayList<Number>)
* in quanto viene violato il principio di sostituzione come
* si evince dal seguente esempio:*/
//ArrayList<Number> integers = new ArrayList<Integer>(); //NON COMPILA
List<Integer> interi = new ArrayList<Integer>();
interi.add(2);
List<Number> numeri = interi; // non compila!
numeri.add(3.14d);
}
}
Programmazione con Java ‐ ArrayList e Generics
Software Architecture Lab
www.sal.disco.unimib.it
45
Esercizio lista concatenata
E
Attiv ita
-
descrizione: String
durataInMinuti: int
svolta: boolean
+
+
+
+
+
+
+
Attivita(descrizione :String, durataInMinuti :int)
getDescrizione() : String
getDurataInMinuti() : int
isSvolta() : boolean
svolta() : void
toString() : String
equals(altraAttivita :Object) : boolean
Nodo
-
dato: E
next: Nodo<E>
+
+
+
+
+
+
Nodo(dato :E, next :Nodo<E>)
getDato() : E
setDato(dato :E) : void
getNext() : Nodo<E>
setNext(next :Nodo<E>) : void
toString() : String
-head
1
concretizza dato in Nodo
E
ListaConcatenata
DemoLista
+
Software Architecture Lab
www.sal.disco.unimib.it
main(args :String[]) : void
+
+
+
+
ListaConcatenata()
aggiungiNodo(nodo :Nodo<E>) : void
aggiungiNodo(elemento :E) : void
toString() : String
Programmazione con Java ‐ ArrayList e Generics
46
23
08/06/2014
Esercizio conclusivo (1/2)
TestCase
Persona
Test
+
+
+
testCentrale() : void
testCentraleEqua1() : void
testCentraleEquaSoloPrioritarie() : void
-
nome: String
indirizzo: String
citta: String
+
+
+
+
+
Persona(nome :String, indirizzo :String, citta :String)
getNome() : String
getIndirizzo() : String
getCitta() : String
toString() : String
-destinatario
-mittente
Lettera
CentraleSmistaPosta
-
filiale: String
+
+
#
#
+
+
CentraleSmistaPosta(filiale :String)
riceviLettera(nuovaLettera :Lettera) : void
posizioneLetteraDaSmistare() : int
getLettera(posizione :int) : Lettera
smistaLettera() : Lettera
toString() : String
#lettere
+
+
-
* +
+
+
+
+
+
PRIORITARIA: int = 1 {readOnly}
TRADIZIONALE: int = 0 {readOnly}
tipoSpedizione: int
Lettera(mittente :Persona, destinatario :Persona, tipoSpedizione :int)
Lettera(mittente :Persona, destinatario :Persona)
getMittente() : Persona
getDestinatario() : Persona
getTipoSpedizione() : int
toString() : String
CentraleSmistaPostaEqua
+
numeroPrioritarieSmistate: int
NUMERO_MAX_PRIORITARIE_CONSECUTIVE: int = 2
+
#
CentraleSmistaPostaEqua(filiale :String)
posizioneLetteraDaSmistare() : int
Exception
DestinatarioNonSpecificatoException
Software Architecture Lab
www.sal.disco.unimib.it
+
DestinatarioNonSpecificatoException()
Programmazione con Java ‐ ArrayList e Generics
47
Esercizio conclusivo (2/2)
•
Entrambi i costruttori di Lettera lanciano eccezione se il mittente è null
Il costruttore di Lettera public Lettera(Persona mittente, Persona
destinatario), imposta il tipo di spedizione a tradizionale
L’associazione tra Lettera e CentraleSmistaPosta va realizzata con un ArrayList
•
Metodi di CentraleSmistaPosta:
•
•
–
–
public void riceviLettera(Lettera nuovaLettera) accoda la nuova lettera
protected int posizioneLetteraDaSmistare(): restituisce la prima prioritaria se c‘è o la prima –
protected Lettera getLettera(int posizione): restituisce la lettera alla posizione specificata tradizionale
–
•
senza rimuoverla dalla lista
public Lettera smistaLettera(): rimuove e restituisce la prima lettera prioritaria che trova. In caso di lettere solo tradizionali, rimuove la prima
Metodi CentraleSmistaPostaEqua
–
–
L’attributo numeroPrioritarieSmistate mantiene il numero di prioritarie attualmente smistate
protected int posizioneLetteraDaSmistare(): ogni NUMERO_MAX_PRIORITARIE_CONSECUTIVE lettere prioritarie smistate, restituisce la posizione della prima tradizionale. Se non esistono lettere prioritarie, restituisce la posizione della prima tradizionale. Se non ha ancora smistato NUMERO_MAX_PRIORITARIE_CONSECUTIVE lettere prioritarie, restituisce la prima prioritaria
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java ‐ ArrayList e Generics
48
24
08/06/2014
Digressione: wildcard
• Le classi e le interfacce possono specificare tipi parametrici che non sono completamente definiti
– Poiché specificano un ampio insieme di tipi, sono conosciuti come wildcard, i.e., caratteri generali
public void metodo(String arg1, ArrayList<?> arg2)
È una stringa
Software Architecture Lab
www.sal.disco.unimib.it
È un ArrayList il cui tipo
base può essere di qualsiasi tipo
Programmazione con Java: Collection Framework
49
Digressione: wildcard
• Può essere messo un bound sul wildcard in modo da specificare che il tipo deve essere un tipo antenato tipo o un tipo discendente di qualche tipo classe o interfaccia
• La notazione <? extends Elemento> specifica che il tipo sostituito deve essere un discendente della classe Elemento
• La notazione <? super Elemento> specifica che il tipo sostituito deve essere un antenato della classe Elemento
Software Architecture Lab
www.sal.disco.unimib.it
Programmazione con Java: Collection Framework
50
25