Generics - oq quer dizer <? super T>?

Olá pessoal
Eu não consegui entender ainda o conceito do super!
o extends blz … List<? extends T> onde ? é qualquer coisa que estenda ou implemente T, dessa forma consigo utilizar a lista polimorficamente, com exceção que não posso inserir elementos, mas oq quer dizer o super?

O Generic (<T>) informa que os objetos guardados no seu List, serão da classe informada. ex.:

class MinhaClasse{
//...
   public void inserir(){
      //  implements
   }
//...
}

Classe que usará a lista:

class Outro{
   List<MinhaClasse> lst = new ArrayList<MinhaClasse>();
   lst.add(new MinhaClasse()); // adiciona novo objeto na lista
   lst.get(0).inserir(); // invoka o método inserir para o 1º reg da lista.
}

Abraços.

Eu cheguei a conclusão que é tudo o contrario do extends, nunca fui atras, foi soh testes que fiz e conclusões que tirei. Exemplo:

vc tem a classe A que implementa Serializable, X que extende de A e C que extende de X.

Se vc tem uma List<? extends A> vc:

    1. não pode incluir nada, porque vc não sabe ateh onde vai o ?.
    1. vai recuperar no minimo um A, vc sabe que a lista eh de algo que extenda A, então o minimo que tem ali eh A.
    1. essa lista pode receber um ArrayList<A>, ArrayList<X> ou ArrayList<C>, pois A,X e C satisfazem o extends de A.

Se vc tem uma List<? super A> vc:

    1. pode incluir de tudo abaixo de A (inclusive), eu imagino como tudo que tem como super A.
    1. vc vai recuperar no minimo um Object, depois no código abaixo acho que fica melhor para visualizar por que.
    1. essa lista pode receber um ArrayList<Object>, ou um ArrayList<Serializable>, mas não pode receber um ArrayList<X> ou ArrayList<C>, pois se recebesse uma List<C> não poderia incluir um X que tem A como super, devem ser listas que deixem incluir tudo que tem A como super, então não estaria certo.

Em codigo, se vc tem esse método:

public void x(List<? super A> list) {
...
}

e eu fizer:

x(new ArrayList<Object>())
x(new ArrayList<Serializable>())
x(new ArrayList<X>())

para o ArrayList de Object e Serializable funciona, pois nessas listas eu consigo incluir A, X e C, mas para o X não funciona. Por esse motivo ele retorna sempre Object, porque pode ser qq lista de algo que eh super de A, e que suporte incluir de A para baixo. Se eu deixasse passar um ArrayList<X> não conseguiria incluir o A, o que não estaria de acordo com a lista que eh ? super A. Agora se dentro do metodo eu tiver:

public void x(List<? super A> list) {
  list.add(new Object());
  list.add(new X());
}

o add para o Object não funciona pois Object não tem A como super, e o add para X funciona, pois este tem.

então, é isso que eu imagino para o super, mas nunca precisei usar, ateh hj soh usei extends

ps: se vc ver um B perdido ai no meio eh porque eu tinha colocado antes classe B, mas ai ele deixa em negrito qdo posto entre <>, então o B virou X, e eu não sei se alterei em tudo.

eh, serve para aquilo que o Fabio falou, com a “vantagem” de por fazer algo do tipo:

List<? super A> l = new ArrayList<Object>();

mas soh deixar incluir objetos to tipo A. Agora o por que fazer isso ai ao inves de

List<A> l = new ArrayList<A>();

eu ateh queria saber, porque ainda nunca senti necessidade de usar…

Sem contar que evita os famosos “casts”:

List<String> list = new ArrayList<String>();

Dessa forma eu defino em tempo de compilação que só haverá Strings dentro do ArrayList. E para recuperar não preciso criar um cast, basta fazer:

String nome = list.get(0)

Ao invés de:

String nome = (String) list.get(0)

Obrigado povo!
eu consegui entender, mas realmente ficou meio no ar, uma situação onde o super seria necessário!
Mas valeu pela explicação!!! :grin:

[code]public class Pai {

public Pai() {
	System.out.println("Construtor da classe pai");
}

public Pai(String nome) {
	System.out.println("Pai da filha: " + nome);
}

public void brigar(String nome) {
	System.out.println("Pai brigando com a filha: " + nome);
}

}[/code]

[code]public class Filha extends Pai {

private String nome;

public Filha() {
	super("Joanna");
}

public static void main(String[] args) {
	Filha filha = new Filha();
	filha.brigar("Joanna");
}

public void brigar(String nome) {
	super.brigar(nome);
}

public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}

}[/code]