Duvida Generics

6 respostas
evertonsilvagomesjav
public class Sub extends Super{

public static void main(String[] args) {

List<Super> lista = new ArrayList();
			
s.say(lista);			

}	

static void say(List<? super Sub> lista){
			
lista.add(new Super()); // aqui erro de compilação...
}		
}

Porque nao posso add um Super no list sendo que a lista é um Super? So da pra add um Sub?

6 Respostas

victorwss
public class Sub extends Super{

    public static void main(String[] args) {
        List<Super> lista = new ArrayList();
        s.say(lista);
    }	

    static void say(List<? super Sub> lista){
        lista.add(new Super()); // aqui erro de compilação...
    }
}

Dá erro porque a lista é de alguma superclasse de Sub ou é a própria classe Sub, mas você não sabe qual. O problema é que pode ser List, List ou List. Para List e List, a adição de um Super está tudo bem. Mas para List, a adição de um Super é uma operação ilegal.

evertonsilvagomesjav

Hum Victor para o compilador entao quando vc passa uma lista ali para List<? super Sub> ele interpreta ela como um “Object” por exemplo?

moacirjava

Lendo este tópico e também a página 339 do livro da kathy (scjp 5) fiquei confuso!
Esse código deveria compilar e executar… :cry:

victorwss
evertonsilvagomesjava:
Hum Victor para o compilador entao quando vc passa uma lista ali para List<? super Sub> ele interpreta ela como um "Object" por exemplo?

Não, você não entendeu. O compilador não interpreta assim. Ele interpreta como "tem que ser compatível com List<Sub> AND com List<Super> AND com List<Object>". Se for incompatível com um deles, dá erro. Um Sub é compatível com todos eles, por isso se você usar lista.add(new Sub()), ele vai compilar. No entanto, lista.add(new Super()) não compila, pois não é compatível com Sub e lista.add(new Object()) também não compila.

Pense assim. Ao invés de Sub e Super, vamos usar Cachorro e Animal para ficar mais claro:
class Exemplo {

    private Cachorro a1 = new Doberman();

    private Animal a2 = new Elefante();

    private Object a3 = new Mesa();

    public void adiciona1(List&lt;? super Cachorro&gt; lista) {
        lista.add(a1); // Compila, pois a1 é do tipo Cachorro.
        lista.add(new Cachorro()); // Dá na mesma do que está acima.
    }

    public void adiciona2(List&lt;? super Cachorro&gt; lista) {
        lista.add(a2); // Erro de compilação. Animal pode não ser um Cachorro. Na verdade é um elefante!
        lista.add(new Animal()); // Não é um cachorro. É incompatível com o caso List&lt;Cachorro&gt;.
    }

    public void adiciona3(List&lt;? super Cachorro&gt; lista) {
        lista.add(a3); // Erro de compilação. O objeto pode não ser um Cachorro. Na verdade é uma mesa!
        lista.add(new Object()); // Não é um cachorro. É incompatível com o caso List&lt;Cachorro&gt;.
    }

    public void chama() {
        List&lt;Cachorro&gt; c = new ArrayList&lt;Cachorro&gt;();
        c.add(new Cachorro());
        adiciona1(c); // Adiciona 2 cachorros na lista de cachorros, tudo bem!
        adiciona2(c); // Se esse método compilasse, acabaríamos com um elefante dentro da lista de cachorros!
        adiciona3(c); // Se esse método compilasse, acabaríamos com uma mesa dentro da lista de cachorros!
    }

    public void chama2() {
        List&lt;Animal&gt; c = new ArrayList&lt;Animal&gt;();
        c.add(new Elefante());
        adiciona1(c); // Adiciona 2 cachorros na lista de animais, tudo bem!
    }

    public void chama3() {
        List&lt;Object&gt; c = new ArrayList&lt;Object&gt;();
        c.add(new Geladeira());
        adiciona1(c); // Adiciona 2 cachorros na lista de objetos, tudo bem!
    }

    public void chama4() {
        List&lt;Poodle&gt; c = new ArrayList&lt;Poodle&gt;();
        c.add(new Poodle());
        adiciona1(c); // Erro: Poodle é específico demais.
                      // Esse método pode adicionar um cachorro que pode não ser poodle.
                      // De fato, vai adicionar um Doberman e um cachorro genérico!
    }
}

Enfim, o compilador olha para o pior caso. Se em adiciona2 você passasse um List<Animal>, não tem problema adicionar um elefante lá. Mas se for um List<Cachorro> tem problema. Como a assinatura do método diz QUE NO PIOR CASO será uma lista de cachorros, então o compilador vê que EXISTE PELO MENOS UM CASO ONDE VAI DAR M..., e por isso ele te dá um erro de compilação.

victorwss

Pense assim: Em que tipo de lista você pode adicionar algum elemento do tipo Super? Em List<Super> e em List<Object> obviamente. List<Sub> não dá.

Em que tipo de lista você pode adicionar algum elemento do tipo Cachorro? Em List<Cachorro>, List<Animal> e List<Object>. List<Poodle> não dá, porque o cachorro pode não ser um Poodle.

List<? super Cachorro> significa: Algum tipo aonde seja possível adicionar um cachorro qualquer, ou seja List<Cachorro>, List<Animal> e List<Object>. Já List<Poodle> não serve, pois não é para qualquer cachorro, apenas para um tipo específico.
Em todos esses (List<Cachorro>, List<Animal> e List<Object> ) eu posso adicionar um cachorro sem problema. No entanto eu não posso adicionar um animal qualquer em todos eles, pois List<Cachorro> é específico demais.

List<? super Sub> significa: Algum tipo aonde seja possível adicionar um Sub, ou seja List<Sub>, List<Super> e List<Object>. Em qulquer um deles eu posso adicionar um Sub seguramente, no entanto o mesmo não ocorre com Super. Eu não posso adicionar um Super qualquer em um List<Sub>, apenas um tipo específico.

evertonsilvagomesjav

Cara nem o livro explicou assim kkk, muito Obrigado Victor pelas explicações vlw mesmo.

Criado 23 de janeiro de 2010
Ultima resposta 25 de jan. de 2010
Respostas 6
Participantes 3