Ao usar <? extends Animal>, estamos dizendo: "Eu posso receber um conjunto que seja um subtipo de List e com o tipo definido de <Animal> ou qualquer coisa que estenda Animal. Ah sim, e PROMETO que não vou ADICIONAR nada ao conjunto".
Assim, é claro que o método addAnimal() não vai compilar nem mesmo com a notação do coringa, porque esse método ADICIONA algo.
public void addAnimal(List <? extends Animal> animals){
animals.add(new Dog()); //NAO! NAO SE PODE ADICIONAR
//SE USARMOS <? extends Animal>
}
Se modificarmos o método de forma que ele não adicione nada, passará a funcionar.
Por que se modificarmos o método de forma que ele não adicione nada, passará a funcionar ?
Ao usar <? extends Animal>, estamos dizendo: "Eu posso receber um conjunto que seja um subtipo de List e com o tipo definido de <Animal> ou qualquer coisa que estenda Animal. Ah sim, e PROMETO que não vou ADICIONAR nada ao conjunto".
Assim, é claro que o método addAnimal() não vai compilar nem mesmo com a notação do coringa, porque esse método ADICIONA algo.
public void addAnimal(List <? extends Animal> animals){
animals.add(new Dog()); //NAO! NAO SE PODE ADICIONAR
//SE USARMOS <? extends Animal>
}
Se modificarmos o método de forma que ele não adicione nada, passará a funcionar.
Por que se modificarmos o método de forma que ele não adicione nada, passará a funcionar ?
Não se pode adicionar nada porque a referencia a lista eh do tipo List <? extends Animal>. Ou seja, vc pode ter atribuido um objeto a essa variavel de referencia do tipo ArrayList <Animal> ou ArrayList <Gato> ou ainda ArrayList<Cachorro. Claro, pré supondo que gato e cachorro herdam de animal.
Se o compilador permitisse adicionar, vc poderia ter atribuido um ArrayList><Gato> para essa referência e depois adicionar um Cachorro.
Se você tirar o método add, o compilador sabe que vc não está adicionando nada, e deixa vc simplesmente ler a lista.
moacirjava
entendi, mas já que não posso adicionar qualquer coisa que seja um animal, por que isso aqui é permitido?
importjava.util.*;classAnimal{}classDogextendsAnimal{privateStringnome="";publicStringgetNome(){returnnome;}publicDog(){}publicDog(Stringa){nome=a;}publicStringtoString(){return"NomedoDog:"+nome;}}publicclassDoutor{publicstaticvoidmain(String...args){List<Dog>dogs=newArrayList<Dog>();dogs.add(newDog("a"));addAnimal(dogs);}//Com esse metodo dah erro// private static void addAnimal(List<? extends Dog> lista){// lista.add(new Dog("b"));// System.out.println(lista);// }//Com esse metodo nao dah erroprivatestaticvoidaddAnimal(List<?superDog>lista){lista.add(newDog("b"));System.out.println(lista);}}
Posso considerar isso como se fosse uma regra? usando <? extends...> não insere nada, <? super...> insere e pronto.
B
brrodo
moacirjava:
entendi, mas já que não posso adicionar qualquer coisa que seja um animal, por que isso aqui é permitido?
importjava.util.*;classAnimal{}classDogextendsAnimal{privateStringnome="";publicStringgetNome(){returnnome;}publicDog(){}publicDog(Stringa){nome=a;}publicStringtoString(){return"NomedoDog:"+nome;}}publicclassDoutor{publicstaticvoidmain(String...args){List<Dog>dogs=newArrayList<Dog>();dogs.add(newDog("a"));addAnimal(dogs);}//Com esse metodo dah erro// private static void addAnimal(List<? extends Dog> lista){// lista.add(new Dog("b"));// System.out.println(lista);// }//Com esse metodo nao dah erroprivatestaticvoidaddAnimal(List<?superDog>lista){lista.add(newDog("b"));System.out.println(lista);}}
Posso considerar isso como se fosse uma regra? usando <? extends...> não insere nada, <? super...> insere e pronto.
Talvez seja mais facil de memorizar se considerar como regra.
Sempre q usar <? extends E> vc não pode adicionar nada à collection. Sempre q for Iterar essa Collection (usando um "for" por herança) deverá referenciar cada elemento como um E ou uma de suas superclasses.
Sempre q usar <? super E> vc pode adicionar qualquer elemento co-variante (que seja um...) de E. Sempre q for Iterar essa Collection (usando um "for" por herança) deverá referenciar cada elemento como um Object.
Sempre q usar <?> considere isto como similar a <? extends Object>, portanto se comportando da mesma maneira. Sempre q for Iterar essa Collection (usando um "for" por herança) deverá referenciar cada elemento como um Object.