java generics

Download Java Generics

If you can't read please download the document

Upload: davide-ficano

Post on 16-Apr-2017

3.451 views

Category:

Technology


4 download

TRANSCRIPT

Diapositiva 1

Java

Generics

Davide [email protected]

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

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

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);

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

Generics
Un esempio

Vector v = new Vector();

v.add("Polly");

// Nessun cast necessario

String s = v.get(0);

// da errore di compilazione

Long l = v.get(0);

Vector v = new Vector();

v.add("Polly");

// necessario il cast

String s = (String)v.get(0);

Senza Generics

Con Generics

Sintassi /1
Definizione

La nuova sintassi prevede la forma Vector

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 v = new Vector();

v.add("Polly");

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

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 v = new Vector();

v.add("Polly");

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

HashMap map = new HashMap();

map.put(10, "dieci");

map.put(20, "venti");

String s = map.get(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 "vecchio" iterator()
public Iterator iterator()
diventa
public Iterator iterator()

Questo permette di avere iterators che non necessitano di casting

Esempi di iterators

Iterator i = v.iterator();

while (i.hasNext()) {

String s = (String)i.next();

System.out.println(s);

}

Iterator i = v.iterator();

while (i.hasNext()) {

String s = i.next();

System.out.println(s);

}

Senza Generics

Con Generics

Generics definiti
dall'utente

I Generics non sono soltato utilizzate dal JDK

Possono essere usati per creare proprie classi

Vediamo in dettaglio come funziona

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 {

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;}

}

Utilizzo classe Coppia

Cane c = new Cane("Fido");

Coppia nome1;

nome1 = new Coppia(c.getNome(), c);

Anatra a = new Anatra("Paperino");

Coppia nome2;

nome2 = new Coppia(a.getNome(), a);

La classe Coppia rappresenta un oggetto con tue valori

Vengono creati due oggetti

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 nome1 = new Coppia(...);

Coppia nome2 new Coppia(...);

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

Peculiarit dei generics /2

Non possibile assegnare un'istanza di una classe parametrica ad un reference con tipo parametrico pi generico

Vector v1 = new Vector();Vector v2 = v1; // errore di compilazione

Domanda 1: Perch questo non consentito?

Domanda 2: E' un difetto oppure un vantaggio?

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

Collezioni di tipo sconosciuto

Abbiamo visto che se si desidera definire una Collection in grado di accettare qualunque tipo, non possiamo usare Vector

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)

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 accetta solo Animale e non sue classi derivate

Vector cani = new Vector();Vector anatre = new Vector();t.stampaAnimali(cani); // errore di compilazionet.stampaAnimali(anatre);// errore di compilazionepublic void stampaAnimali(Vector c) { ... }

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