Generics - coringas

0 respostas
L

Então pessoal, tava vendo mais a fundo aqui generics, mas não achei muita coisa aqui no forum (topicos e tal). Bem, mexo a um tempinho ja com generics, mas sempre o basico e tal, nunca precisei usar os curinhas (?). Bem dei uma olhada e fiz um exemplo, para eu deixar aqui e estudar/lembrar já que é algo que não uso diariamente (os coringas - ?). Queria que vocês dessem uma olhada se minhas conclusões estão corretas, e se possivel me darem uns exemplos de quando vocês sentiram necessidade de usar <? super XXX>, eu geralmente uso <T extends XXX>, no maximo mesmo, usei um <? extends XXX> mas nunca <? super XXX>

Segue meu código de exemplo (deem uma lida nos meus comentários para eu saber se é assim como estou pensando)

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

//informações de http&#58;//www.argonavis.com.br/cursos/java/j100/tiger.html#j5-genericos 
public class Generics
&#123;
   public class A implements Serializable
   &#123;
      public int a = 1;
   &#125;

   public class B extends A
   &#123;
      public int b = 2;
   &#125;

   public class C extends B
   &#123;
      public int c = 3;
   &#125;

   public static void main&#40;String&#91;&#93; args&#41;
   &#123;
      new Generics&#40;&#41;.a&#40;&#41;;
   &#125;

   public void a&#40;&#41;
   &#123;

      // teste1&#40;new ArrayList&lt;A&gt;&#40;&#41;&#41;; // "A" não extende "B" &#40;erro&#41;
      teste1&#40;new ArrayList&lt;B&gt;&#40;&#41;&#41;; // "B" eh "B"
      teste1&#40;new ArrayList&lt;C&gt;&#40;&#41;&#41;; // "C" extende "B"

      // teste2&#40;new ArrayList&lt;A&gt;&#40;&#41;&#41;; // "A" não extende "B" &#40;erro&#41;
      teste2&#40;new ArrayList&lt;B&gt;&#40;&#41;&#41;; // "B" eh "B"
      teste2&#40;new ArrayList&lt;C&gt;&#40;&#41;&#41;; // "C" extende "B"

      teste4&#40;new ArrayList&lt;Object&gt;&#40;&#41;&#41;; // "Object" eh super de "A"
      teste4&#40;new ArrayList&lt;Serializable&gt;&#40;&#41;&#41;; // "A" implementa Serializable
      teste4&#40;new ArrayList&lt;A&gt;&#40;&#41;&#41;; // "A" eh "A"
      // teste4&#40;new ArrayList&lt;B&gt;&#40;&#41;&#41;; // "B" não eh super de "A" &#40;erro&#41;
      // teste4&#40;new ArrayList&lt;C&gt;&#40;&#41;&#41;; // "C" não eh super de "A" &#40;erro&#41;

      teste3&#40;new ArrayList&lt;B&gt;&#40;&#41;, new B&#40;&#41;&#41;; // "B" extends "B"
      teste3&#40;new ArrayList&lt;B&gt;&#40;&#41;, new C&#40;&#41;&#41;; // "C" extends "B"
      teste3&#40;new ArrayList&lt;C&gt;&#40;&#41;, new C&#40;&#41;&#41;; // "C" extends "B"
      // teste3&#40;new ArrayList&lt;C&gt;&#40;&#41;, new B&#40;&#41;&#41;; //porque a lista "C" não aceita o tipo "B" &#40;erro&#41;

   &#125;

   /**
    * Aceita qualquer lista de objetos que extendem "B", ou seja "C" ou "B". Por isso que ao remover o objeto ele é um "B", pois pode ser uma lista de
    * qualquer coisa abaixo de "B" &#40;o que sera no minimo um B, garantido&#41;. E para incluir ele não sabe qual o tipo, pois o tipo é um curinga &#40;?&#41; que
    * extende "B" e ateh onde o ? chega eh desconhecido, poderia ser até "C", nesse caso não poderia inserir "B", ou o ? poderia ser mais baixo que
    * "C", então não poderia incluir nem "C" nem "B", enfim, não se sabe o que é ?, então não pode incluir. Como se fosse uma lista de objetos
    * desconhecidos abaixo de "B"..
    */
   public void teste1&#40;List&lt; ? extends B&gt; col&#41;
   &#123;
      B x = col.get&#40;1&#41;;
      // col.add&#40;new C&#40;&#41;&#41;; //não sei que nivel incluir &#40;erro&#41;
   &#125;

   /**
    * Idem ao teste1&#40;&#41;, porem aqui eu posso incluir um Objecto do tipo T &#40;é o delimitador de ateh onde chega o coringa&#41;, com isso eu poderia receber
    * por parametro um objeto do tipo T e incluir. &#40;ver teste3&#41;
    */
   public &lt;T extends B&gt; void teste2&#40;List&lt;T&gt; col&#41;
   &#123;
      B x1 = col.remove&#40;1&#41;;
      T x2 = col.remove&#40;1&#41;;
      // col.add&#40;new C&#40;&#41;&#41;; //não pode incluir &#40;erro&#41;
   &#125;

   /**
    * Aqui o add funciona, mas é porque eu tenho um delimitador do "?" que é T.
    */
   public &lt;T extends B&gt; void teste3&#40;List&lt;T&gt; col, T obj&#41;
   &#123;
      col.add&#40;obj&#41;;
   &#125;

   /**
    * Lista de objetos que forem super de "A", ou seja, "Object", "A" ou qualquer coisa que "A" extende ou implementa &#40;contrario do extends&#41;, por isso
    * para remover, o método devolve um objeto do tipo "Object". Para incluir a abordagem é diferente, vai incluir qualquer objeto "A" ou que tenha
    * como super "A", ou seja "B" ou "C", porque diferente do &lt;? extends A&gt;, este eu sei até onde chega o curinga, no máximo até "A", então incluo
    * "A". Com isso, da para receber uma Lista de "Object" &#40;que é super de "A"&#41; e incluir objetos "B" ou "C" que são extends de "A", ao remover, o
    * casting para "B" ou "C" funciona normalmente.
    */
   public void teste4&#40;List&lt; ? super A&gt; col&#41;
   &#123;
      // col.add&#40;new Object&#40;&#41;&#41;; // erro, Object não tem A como super.
      col.add&#40;new A&#40;&#41;&#41;;
      col.add&#40;new B&#40;&#41;&#41;;

      // casting funciona normal
      A z1 = &#40;A&#41; col.get&#40;0&#41;; // retorna Object
      B z2 = &#40;B&#41; col.get&#40;1&#41;; // retorna Object
      System.out.println&#40;z1.a&#41;;
      System.out.println&#40;z2.b&#41;;
   &#125;

&#125;
Criado 20 de outubro de 2006
Respostas 0
Participantes 1