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
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".
e preciso declarar um método contendo um parâmetro com uma coleção polimórfica...
voidgo(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...
voidgo(List<?extendsAnimal>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.
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).