Java Generics

  • 2,980 views
Uploaded on

Introduzione ai Generics in Java

Introduzione ai Generics in Java

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • Grazie!
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
2,980
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
100
Comments
1
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Java Generics Davide Ficano [email_address]
  • 2. Le collezioni di oggetti
    • Java mette a disposizione classi per contenere oggetti
      • Liste,Vettori
      • HashTable
      • Set
    • Sino a Java 1.4 queste classi lavoravano solo con Object, a partire da Java 1.5 e' stato introdotta una nuova sintassi
  • 3. Object e le collezioni
    • Object è la superclasse implicita di qualunque oggetto
    • Object è un tipo generico , dal momento che qualunque classe è un Object
    • Grazie a questa proprietà di Object, è possibile creare oggetti di dimensione variabile come Vector
  • 4. Difetti delle collezioni di Object
    • Utilizzando queste classi ci si rende subito conto che
      • si ha la necessità di ricorrere al casting per recuperare gli oggetti presenti nel contenitore
      • non esiste nessun controllo sul tipo di oggetti che effettivamente vengono inseriti nel Vector; se per errore si inserisce in v un oggetto diverso da String, la cosa verrà notata soltanto in fase di esecuzione
    • Vector v = new Vector();
    • v.add( "Polly" );
    • // necessario il cast
    • String s = (String)v.get(0);
    • Vector v = new Vector();
    • v.add( "Polly" );
    • // ClassCastException
    • Long l = (Long)v.get(0);
  • 5. Generics Polimorfismo Parametrico
    • Per risolvere i problemi citati in Java 1.5 è stato introdotto il concetto di Generics
    • I Generics hanno una nuova sintassi
    • Il tipo della collezione si dichiara in fase di definizione dell'oggetto
    • Errori di assegnazioni a oggetti non corretti vengono segnalati in fase di compilazione anziché in fase di esecuzione
  • 6. Generics Un esempio
    • Vector<String> v = new Vector<String>();
    • v.add( &quot;Polly&quot; );
    • // Nessun cast necessario
    • String s = v.get(0);
    • // da errore di compilazione
    • Long l = v.get (0);
    • Vector v = new Vector();
    • v.add( &quot;Polly&quot; );
    • // necessario il cast
    • String s = (String)v.get(0);
    Senza Generics Con Generics
  • 7. Sintassi /1 Definizione
    • La nuova sintassi prevede la forma Vector<E>
    • La E tra parentesi angolari denota un Tipo Parametrico deciso dall'utilizzatore
    • Grazie alla nuova sintassi il controllo sui tipi viene effettuato dal compilatore
    • Vector<String> v = new Vector<String>();
    • v.add( &quot;Polly&quot; );
    • v.add(new Integer(10)) ; // da errore di compilazione
    • String s = v.get(0); // Nessun cast necessario
    • Long l = v.get (0); // da errore di compilazione
  • 8. Sintassi /2 Metodi
    • La classe Vector ha dei metodi che devono lavorare con i generics ad esempio add()
    • I metodi vengono dichiarati utilizzando il meta tipo
    boolean add(E o) // prende in ingresso un generic E get( int index) // restituisce un generic
    • Il simbolo E verrà sostituito automaticamente con il tipo dichiarato in fase di creazione
    • Vector<String> v = new Vector<String>();
    • v.add( &quot;Polly&quot; );
  • 9. Generics Non solo Vector
    • Vector è solo un esempio, i generics possono essere usati ad esempio sugli oggetti java.util.Map
    • HashMap lavora con la coppia chiave, valore che vengono gestiti entrambi come generics
      • HashMap<K,V>
    • HashMap<Integer, String> map = new HashMap<Integer, String>();
    • map.put(10, &quot;dieci&quot; );
    • map.put(20, &quot;venti&quot; );
    • String s = map.get(10);
  • 10. Generics e valori di ritorno
    • Gli Identificatori generics possono restituire come valore di ritorno una classe parametrica dello stesso tipo di quello dichiarato al costruttore.
    • Il &quot;vecchio&quot; iterator() public Iterator iterator() diventa public Iterator<E> iterator()
    • Questo permette di avere iterators che non necessitano di casting
  • 11. Esempi di iterators
    • Iterator i = v.iterator();
    • while (i.hasNext()) {
    • String s = (String)i.next();
    • System. out .println(s);
    • }
    • Iterator<String> i = v.iterator();
    • while (i.hasNext()) {
    • String s = i.next();
    • System. out .println(s);
    • }
    Senza Generics Con Generics
  • 12. Generics definiti dall'utente
    • I Generics non sono soltato utilizzate dal JDK
    • Possono essere usati per creare proprie classi
    • Vediamo in dettaglio come funziona
  • 13. Classe parametrica
    • Linea 1: La classe viene dichiarata con due tipi generics
    • Gli attributi ed i metodi fanno riferimento al meta tipo
    • public class Coppia<K, V> {
    • private K k ;
    • private V v ;
    • public Coppia(K k, V v) {
    • this . k = k;
    • this . v = v;
    • }
    • public K getKey(){ return k ; }
    • public V getValue(){ return v ; }
    • }
  • 14. Utilizzo classe Coppia
    • Cane c = new Cane( &quot;Fido&quot; );
    • Coppia<String, Cane> nome1;
    • nome1 = new Coppia<String, Cane>(c.getNome(), c);
    • Anatra a = new Anatra( &quot;Paperino&quot; );
    • Coppia<String, Anatra> nome2;
    • nome2 = new Coppia<String, Anatra>(a.getNome(), a);
    • La classe Coppia rappresenta un oggetto con tue valori
    • Vengono creati due oggetti
  • 15. Peculiarità dei generics /1
    • Tutte le istanze di una classe generica condividono la stessa classe di base, anche se vengono specializzate in modo differente.
    • Coppia<String, Cane> nome1 = new Coppia<String, Cane>(...);
    • Coppia<String, Anatra> nome2 new Coppia<String, Anatra>(...);
    • Ci si aspetta che le due classi siano diverse per tipo ma esse condividono la stessa classe base quindi il confronto
      • nome1.getClass() == nome2.getClass()
    • ritorna true
  • 16. Peculiarità dei generics /2
    • Non è possibile assegnare un'istanza di una classe parametrica ad un reference con tipo parametrico più generico
    Vector<String> v1 = new Vector<String>(); Vector<Object> v2 = v1; // errore di compilazione
    • Domanda 1: Perchè questo non è consentito?
    • Domanda 2: E' un difetto oppure un vantaggio?
  • 17. Type safety sicurezza nell'assegnamento dei tipi
    • Se una simile operazione fosse consentita, si otterrebbero due reference di tipo parametrico diverso che puntano allo stesso Vector di String.
    • Potremmo inserire all'interno di tale vettore oggetti differenti da String usando il reference v2:
    • v2.add(new Object); // violazione della type safety
  • 18. Collezioni di tipo sconosciuto
    • Abbiamo visto che se si desidera definire una Collection in grado di accettare qualunque tipo , non possiamo usare Vector<Object>
    • Essa denota una Collection in grado di accettare unicamente oggetti di tipo Object
    • Per risolvere quello problema è possibile definire generics di tipo parametrico sconosciuto
    • Questo si fa utilizzando il carattere '?' (punto interrogativo)
  • 19. Utilizzo /1
    • Il codice riportato di seguito
      • crea due vettori che contengono rispettivamente solo Cani e solo Anatre (ricordiamo che entrambi gli oggetti estendono la classe Animale)
      • chiama un metodo in grado di stampare oggetti di tipo Animale
    • Sappiamo, per quanto detto prima, che Vector<Animale> accetta solo Animale e non sue classi derivate
    Vector<Cane> cani = new Vector<Cane>(); Vector<Anatra> anatre = new Vector<Anatra>(); t.stampaAnimali(cani); // errore di compilazione t.stampaAnimali(anatre); // errore di compilazione public void stampaAnimali(Vector<Animale> c) { ... }
  • 20. Utilizzo /2 Upper bound
    • Il metodo stampaAnimali deve essere reso capace di gestire la gerarchia Animale
    • Si utilizza la tecnica upper bound che permette di ricevere elementi di tipo Animale e di tutte le sue sottoclassi
    • La sintassi utilizza il wildcard e la parola extends
    public void stampaAnimali(Vector<? extends Animale> c) { ... }
  • 21. Utlizzo /3 Lower bound
    • Molto meno usato del precedente, il lower bound permette di ricevere solo oggetti di un certo tipo o di una sua superclasse
    • La sintassi utilizza il wildcard e la parola super
    public void stampaCani(Vector<? super Cane> c) { ... }