PREV Dichiarazioni di variabili NEXT Reificazione
Migrare gradualmente il codice all'utilizzo dei generics (evoluzione) senza modifche radicali (rivoluzione)
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
E' quindi necessario procedere per passi
I raw types sono la controparte legacy dei generic types
Generic | Raw |
---|---|
Stack<E> | Stack |
List<E> | List |
ArrayStack<E> | ArrayStack |
Dovendo utilizzare client con librerie abbiamo 4 casi
Client / Libreria | Libreria Generic | Libreria Legacy |
---|---|---|
Client Generic | CG,LG | CG,LL |
Client Legacy | CL,LG | CL,LL |
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)
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
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
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
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)