Il contenuto di questo sito è rilasciato sotto licenza Creative Commons License se non specificato diversamente

Evoluzione, non rivoluzione

PREV Dichiarazioni di variabili NEXT Reificazione

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)

 
java/generics/evoluzione_non_rivoluzione.txt · Ultima modifica: 2012/03/11 12:06 da fcasadei
 
Recent changes RSS feed