Originariamente inviato da Hysoka
perdona la mia perseveranza, ma io non ci vedo niente di strano nel fare quel codice.
Se ... e ripeto se quella assegnazione fosse permessa allora si potrebbe inserire un String in un ArrayList<Object> che in realtà farebbe riferimento ad un ArrayList<Number>. E senza avere alcun errore/warning in compilazione!!
E tutti questi bei discorsi sui generics e sulla type-safety andrebbero a farsi friggere!!
Tutto il problema, a monte della proibizione di quell'assegnamento, è la "erasure". A runtime la collezione è solo un ArrayList e basta, non c'è scritto da nessuna parte (né all'interno della collezione né altrove) che è di Object o String o altro.
E per completare la discussione c'è da dire che si possono comunque combinare casini. Sfruttando il "raw type".
codice:
ArrayList<Number> numArr = new ArrayList<Number>();
ArrayList arr = numArr; // OK, nessun errore
arr.add("pippo"); // warning!!!
Ma almeno il compilatore emette un warning:
warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.ArrayList
Come a dire: "guarda che stai facendo qualcosa che probabilmente può dare problemi". E poi appunto sono affari del programmatore ....
Originariamente inviato da Hysoka
ma tutto quello che inserisco non lo posso usare come Object? O peggio, castarlo?
Certo ... questo sicuramente.
codice:
ArrayList<Number> numArr = new ArrayList<Number>();
// ....
Object o = numArr.get(0);
Ma qui non si stava parlando di cosa contengono le collezioni. Ma di come il wildcard (eventualmente con extends/super) fornisce una forma di "polimorfismo" sul tipo parametrico!!!
Faccio un altro esempio: voglio realizzare un metodo che inserisce un certo numero di valori casuali interi in una collezione. Senza il wildcard si dovrebbe fare:
codice:
public static void addRandom(List<Integer> lista, int count) {
Random r = new Random();
while (count-- > 0) {
lista.add(r.nextInt());
}
}
È chiaramente limitato ... posso solo passare un List<Integer> (es. ArrayList<Integer> o LinkedList<Integer>). Non posso passare un ArrayList<Number> o ArrayList<Object>.
Anche se a rigor di logica non sarebbe sbagliato (un Integer può stare benissimo in un ArrayList<Number> o ArrayList<Object>!!!).
Con un "lower bounded" wildcard:
codice:
public static void addRandom(List<? super Integer> lista, int count) {
Random r = new Random();
while (count-- > 0) {
lista.add(r.nextInt());
}
}
Si può passare un ArrayList<Number> o ArrayList<Object>. Il 'super' indica proprio che il tipo della collezione accettato può essere Integer o un suo super-tipo.