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
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
- …
Raw type e generic type
I raw types sono la controparte legacy dei generic types
Generic | Raw |
---|---|
Stack<E> | Stack |
List<E> | List |
ArrayStack<E> | ArrayStack |
Casi di evoluzione
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 |
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
Un oggetto “parametrico” può quindi essere utilizzato quando ci si aspetta un 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
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 (!!!)
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