Supondo que Animal é uma classe e que Dog estende Animal, a declaração abaixo com arrays é permitida:
Animal [] animals = new Dog[](); Mas a seguinte declarção com generics não é válida:
List<Animal> = new ArrayList<Dog>();O tipo genérico sempre tem de ser o mesmo.
Essa restrição impede o surgimento de situações de risco como a seguinte:
public static void useAnimals(List<Animal> animais){
animais.add(new Dog());
}
public static void main(....){
List<Cat> cat = new ListArray<Cat>();
useAnimals(cat);
}
Se o compilador não barrasse essa possibilidade, haveria um erro ao se tentar adicionar um objeto do tipo Dog em uma lista do tipo genérico Cat.
Existe, no entanto, a possibilidade de passar como argumento uma coleção com um tipo genérico distinto daquele declarado no método. Por exemplo:
public void useAnimals(List<? extends Animals> animals){}Agora posso passar um ArrayList<Cat> como argumento do método useAnimals. No entanto, ao usar essa sintaxe,
? extends, me comprometo a não usar o método
add da coleção. Isso impede novamente o surgimento da situação indesejada mencionada acima. Ocorrerá um erro em tempo de compilação se houver uma tentativa de usar o referido método. Com esta sintaxe, qualquer coleção List com o tipo genérico Animal ou uma classe herdeira de Animal pode ser usada como argumento do método.
Outra possibilidade é a seguinte:
public void useAnimals(List<? super Dog> animals){}Com essa sintaxe indico que qualquer coleção List com o tipo genérico Dog ou uma superclasse de Dog pode ser usada como argumento deste método. Agora não existe a restrição de não poder usar o método
add de List.