Dúvidas Generics/Polimorfismo - OCJP

5 respostas
diegofss11

E ae galera, beleza ?

Estou com algumas dúvidas inerentes ao Polimorfismo aplicado aos Generics.

Onde não posso usar coringas:

Na criação dos objetos: List<?> f = new ArrayList<? extends Animal>();
Usar coringas ? apenas: Argumentos, variáveis e tipos de retornos.

List<? extends Animal> li = new ArrayList();

ArrayList<?> list = new ArrayList();

ArrayList<? extends Girafa> g = new ArrayList();

//não posso add nada aqui g.add(new Gir()); não compila

Eu li isso no camilolopes.wordpress, mas não entendi.

Edit: Entendido.

5 Respostas

belashi

Diego, o que exatamente você não entendeu?

diegofss11

O porque da utilização dos coringas nas declarações e criação de objetos.

belashi

Bom, vou ver se consigo lhe ajudar...

A declaração de tipos em Java serve para oferecer proteção em tempo de Compilação.

Por exemplo, o compilador não tem como "controlar" o que é inserido em uma lista declarada sem um tipo genérico.

List l = new ArrayList(); //é válido acrescentar qualquer objeto nesta list

Já em uma lista com o tipo genérico declarado o compilador consegue garantir que apenas objetos que passem no teste IS-A (É-UM) possam ser inseridos naquela determinada lista.

List<Number> l = new ArrayList<Number>(); //a lista pode receber Integer, Float, Number, int (autoboxing) e etc...

Até ai tudo certo...

O que ocorre com a declaração de genéricos é que quando ela é feita, aquela declaração torna o nome da coleção "uma coisa única".

uma List é uma List e somente isso. O polimorfismo não é válido para a declaração de tipos. Ou seja, List é diferente de List que é diferente de List, que é diferente de List.

O polimorfismo com coleções só é válido para o tipo base da coleção, ou seja:

List<String> l = new ArrayList<String>(); //OK, o polimorfismo só foi usado com o tipo base e não com a declaração de tipo genérica

ArrayList<Object> = new ArrayList<String>(); //INVÁLIDO, o polimorfismo não funciona com os tipos genéricos.

Acredito que uma analogia que possa ser feita é que quando tentamos atribuir um objeto ArrayList a uma variável de referência ArrayList para o compilador é como se estivessemos fazendo uma atribuição de tipos diferentes, como String s = new Integer(4);

É aí que entram os wildcards. Eles servem para que um método por exemplo declare como parâmetro uma Lista com tipo genérico "polimórfico".

Se eu tenho por exemplo a hierarquia
class Animal { }
class Dog extends Animal { } 
class Cat extends Animal { }

e preciso declarar um método contendo um parâmetro com uma coleção polimórfica...

void go(List<Animal> l) { }

Válido, porém só poderei passar referências do tipo List. Se eu tiver uma referência do tipo List o compilador irá dar "chilique".

Agora utilizando wildcards...

void go(List<? extends Animal> l) { }

Agora sim, posso passar uma List como argumento para o método.

Mas lembre-se, a declaração de parâmetros com o uso de wildcards é uma operação onde não se conhece o tipo que será utilizado, ou seja, não é válido fazer mudanças na coleção. Apenas é válida a consulta.

Se falei alguma asneira me corrijam, espero poder ter ajudado.

Fonte: http://docs.oracle.com/javase/tutorial/java/generics/

diegofss11

Entendi ! Muito obrigado,

Ataxexe

Apenas complementando: existe a possibilidade de usar o super em vez do extends no curinga. Dessa forma você pode usar as superclasses em vez das subclasses. É exatamente o inverso do extends.

Exemplo: se você for filtrar uma coleção, pode receber um filtro assim:

Dessa forma pode passar filtros mais genéricos pra ela (no caso do exemplo do nosso amigo, um filtro do tipo Animal caberia caso a coleção fosse de objetos do tipo Cachorro).

Criado 30 de julho de 2012
Ultima resposta 2 de ago. de 2012
Respostas 5
Participantes 3