lunedì 5 marzo 2012

Introduzione a java e generics parte 5 - Evoluzione, non rivoluzione

Migrare gradualmente il codice all'utilizzo dei generics (evoluzione) senza modifche radicali (rivoluzione)

Evoluzione

L'implementazione dei generics permette che il vecchio codice venga compilato ed eseguito anche con l'utilizzo delle nuove librerie L'evoluzione è più forte della retro compatibilità: non esistono più versioni delle classi e delle librerie ma una sola versione (grazie alla type erasure) compatibile
Non sempre è possibile mettere mano a tutto il codice
  • È costoso
  • Non abbiamo accesso ai sorgenti
  • Possiamo mettere le mani solo sul client o sulla libreria
E' quindi necessario procedere per passi

Raw type e generic type

I raw types sono la controparte legacy dei generic types
GenericRaw
Stack<E> Stack
List<E> List
ArrayStack<E> ArrayStack

Casi di evoluzione

Dovendo utilizzare client con librerie abbiamo 4 casi
Client / LibreriaLibreria GenericLibreria Legacy
Client Generic CG,LG CG,LL
Client Legacy CL,LG CL,LL

Client Generic, Libreria Generic

Non pone grossi problemi (è il punto di arrivo). Per arrivare a questo punto di norma tutte le occorrenze di Object vengono sostituite con opportuni parametri di tipo (solo dove ha senso)

Client Legacy, Libreria Legacy

Di norma è il punto di partenza dell'evoluzione in cui sono presenti solo raw type
public static void fai(List l) { ...}
questo codice genera un warning:
List is a raw type. References to generic type List<E> should be parametrized

Client Legacy, Libreria generica

E' il caso più importante di retro compatibilità: il Collection framework di java 5 deve funzionare con i client di java 1.4. Per supportare l'evoluzione, per ogni parametro generico java riconosce anche il suo raw type
Ogni tipo parametrico è sottotipo del corrispondente raw type
Un oggetto “parametrico” può quindi essere utilizzato quando ci si aspetta un raw type

Unchecked conversion warning

Di norma è un errore utilizzare un supertipo di T quando ci si aspetta un oggetto di tipo T.
Eccezione alla regola: è possibile utilizzare un raw type al posto di uno dei corrispondenti tipi parametrici
Viene tuttavia generato un unchecked conversion warning
List a = new ArrayList<String>(); // OK, normale sottotipizzazione
List<String> x = new ArrayList(); // OK ... ma genera un Unchecked Conversion Warning
Type safety: the expression of type ArrayList needs unchecked conversion to conform to List<String>
 
Unchecked conversion warning indica che il compilatore non è in grado di ofrire le stesse garanzie che sono possibili quando i generics vengono utilizzati in maniera uniforme.
Vengono comunque assicurate le stesse (???) garanzie di quando non si utilizzano per niente i generics (!!!)

Non vale la cast iron guarantee

Client generico, Libreria Legacy

List l
= new ArrayList<String>();
l.add(elem);
 
Il codice compila ma viene generato un Unchecked Call Warning
 
Pippo.java:7: warning: [unchecked] unchecked call to add(E) as a member of the raw
type java.util.List
l.add(elem);
 
:!: Se i warning vi danno doia …
@SuppressWarnings("unchecked")
(a vostro rischio e pericolo)

Nessun commento:

Posta un commento