I generics permettono di creare classi, interfacce e metodi con parametri di tipo, il che garantisce il controllo del tipo in fase di compilazione e aiuta a evitare ClassCastException.
Caratteristiche chiave e insidie:
new List<String>[10] — errore di compilazione.T obj = new T();if(obj instanceof List<String>) — errore.? extends T — covarianza (lettura), ? super T — controvarianza (scrittura).Esempio:
// Approccio covariante per la lettura void printNumbers(List<? extends Number> numbers) { for (Number n : numbers) { System.out.println(n); } } // Approccio controviante per la scrittura void addIntegers(List<? super Integer> list) { list.add(10); } }
Domanda: "Qual è la differenza tra List<Object> e List<?>? È possibile inserire qualsiasi oggetto in List<?>?"
Risposta: No, in List<?> non è possibile aggiungere nulla (tranne null), perché il compilatore non sa quale parametro di tipo ci sia esattamente. In List<Object> è possibile aggiungere qualsiasi oggetto.
Esempio:
List<?> list1 = new ArrayList<String>(); // list1.add("test"); // Errore di compilazione! List<Object> list2 = new ArrayList<>(); list2.add("test"); // OK
Storia
Un team di sviluppatori ha tentato di implementare una cache basata su un array di tipo parametrizzato
T[]. A causa del type erasure e dell'impossibilità di creare array di tipo generico, la soluzione non ha funzionato come previsto: si otteneva un arrayObject[], che portava a ClassCastException durante i cast a runtime.
Storia
In uno dei microservizi, uno sviluppatore ha tentato di implementare un receiver utilizzando List<?> come parametro, e ha cercato di modificare la collezione. Questo ha causato un errore di compilazione e ha ritardato la release, poiché è stato necessario rifattorizzare la logica tenendo conto del PECS.
Storia
Nel progetto di integrazione con un sistema esterno, uno sviluppatore ha commesso un errore sovrascrivendo una collezione di un tipo con un'altra tramite un raw-type non gestito: List list = new ArrayList<String>(), il che ha portato a ClassCastException e crash del servizio in produzione durante il tentativo di castare gli elementi a altri tipi.