Pessoal,
estou com essa dúvida de generics, alguém pode me explicar este código:
public class GenericsTest {
public static void main(String[] args) {
List<Integer> myList = new ArrayList<Integer>();
Bar bar = new Bar();
bar.doInsert(myList);
}
private static class Bar {
public Bar() { }
private void doInsert(List<? super Integer> myList) { // OK, compila
myList.add(new Integer(5));
}
}
}
Mas trocando abaixo…
private void doInsert(List<? extends Number> myList) {
myList.add(new Integer(5)); // Não compila, mas deveria pois Integer extends Number não?
}
Obrigado.
Relendo a Sierra-Bates,
diferentemente de arrays (ArrayStoreException), a JVM não provê uma exceção específica para generics caso eu tente adicionar algo que não extenda ‘Number’.
Java 6 (Sierra-Bates), págs. 615 a 622.
Ele não deixa você inserir porque a referência “não sabe” em runtime qual o tipo que está dentro da coleção. Tudo o que o método sabe é que é alguma lista com elementos que extendem Number, porém o método “não sabe” qual o tipo exato desta lista. Como você disse, Integer extende Number, porém é correto chamar o método com uma variável do tipo List, List, ou seja, uma lista de qualquer classe que extenda Number. Como pela assinatura do método não tem como ele saber exatamente qual o tipo que foi passado, ele não deixa você incluir, pois embora seja possível incluir um Integer se a lista original era List, seria um erro incluir em qualquer outro caso, como por exemplo se na chamada a lista era List.
Existe uma regra pra isso:
1 - se você quer apenas ler os elementos da coleção parada para o método, utilize <? extends Tipo>
2 - se você quer apenas adicionar ou alterar os elementos da coleção passada para o método, utilize <? super Tipo>
3 - se você quer ler e alterar os elementos da coleção, utilize List, porém neste caso a chamada ao método só funcionará com List