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