Cap. 7 - Generics e Collections, JAVA 5 pág 339

5 respostas
moacirjava

livro da kathy:
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 &lt;? extends Animal&gt; animals){ animals.add(new Dog()); //NAO! NAO SE PODE ADICIONAR //SE USARMOS &lt;? extends Animal&gt; }

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 ?

5 Respostas

rodrigo.bossini

moacirjava:
livro da kathy:
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 &lt;? extends Animal&gt; animals){ animals.add(new Dog()); //NAO! NAO SE PODE ADICIONAR //SE USARMOS &lt;? extends Animal&gt; }

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?
import java.util.*;

class Animal{}
class Dog extends Animal{
    private String nome = &quot;&quot;;
    public String getNome(){return nome;}
    public Dog(){}
    public Dog(String a){nome = a;}
    public String toString(){return &quot;Nome do Dog: &quot; + nome;}
}
public class Doutor {
    public static void main(String... args){
        List&lt;Dog&gt; dogs = new ArrayList&lt;Dog&gt;();
        dogs.add(new Dog(&quot;a&quot;));
        addAnimal(dogs);
    }

    //Com esse metodo dah erro
//    private static void addAnimal(List&lt;? extends Dog&gt; lista){
//        lista.add(new Dog(&quot;b&quot;));
//        System.out.println(lista);
//    }

    //Com esse metodo nao dah erro
    private static void addAnimal(List&lt;? super Dog&gt; lista){
        lista.add(new Dog(&quot;b&quot;));
        System.out.println(lista);
    }
}

Posso considerar isso como se fosse uma regra? usando <? extends...> não insere nada, <? super...> insere e pronto.

B
moacirjava:
entendi, mas já que não posso adicionar qualquer coisa que seja um animal, por que isso aqui é permitido?
import java.util.*;

class Animal{}
class Dog extends Animal{
    private String nome = &quot;&quot;;
    public String getNome(){return nome;}
    public Dog(){}
    public Dog(String a){nome = a;}
    public String toString(){return &quot;Nome do Dog: &quot; + nome;}
}
public class Doutor {
    public static void main(String... args){
        List&lt;Dog&gt; dogs = new ArrayList&lt;Dog&gt;();
        dogs.add(new Dog(&quot;a&quot;));
        addAnimal(dogs);
    }

    //Com esse metodo dah erro
//    private static void addAnimal(List&lt;? extends Dog&gt; lista){
//        lista.add(new Dog(&quot;b&quot;));
//        System.out.println(lista);
//    }

    //Com esse metodo nao dah erro
    private static void addAnimal(List&lt;? super Dog&gt; lista){
        lista.add(new Dog(&quot;b&quot;));
        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.

Tomara q tenha dado pra entender hehe.

LPJava

dar uma olhada nesse meu post.

moacirjava

:thumbup:

Criado 25 de abril de 2009
Ultima resposta 27 de abr. de 2009
Respostas 5
Participantes 4