Entendendo Generics em Java

Parametrização de Tipos com Generics

Generics permitem a parametrização de tipos de dados, tratando tipos como parâmetros. Ao utilizar um tipo genérico, você especifica o tipo concreto a ser usado.

Generics em Classes

Ao declarar um tipo genérico para uma classe, todos os membros não estáticos dentro dessa classe podem utilizar o parâmetro de tipo.

A sintaxe para definir uma classe genérica é:

```

public class NomeClasse<T, A, B, C> { private T variavel;

public T metodo(T nomeParametro, ...) {
    // corpo do método
}

}

  

O parâmetro de tipo em uma classe genérica determina os tipos de dados das variáveis de instância e dos tipos de retorno dos métodos da classe.

Veja um exemplo de uma classe `Fruta` genérica:

 
    ```

public class Fruta<T> {
    private T fruta;

    public void definirFruta(T fruta) {
        this.fruta = fruta;
    }

    public T obterFruta() {
        return fruta;
    }
}
    

E uma classe Maca:

```

public class Maca { @Override public String toString() { return "Maçã"; } }

  

Exemplo de teste:

 
    ```

public class TesteGenerics {
    public static void main(String[] args) {
        Fruta<Maca> f1 = new Fruta<>();
        f1.definirFruta(new Maca());
        System.out.println(f1.obterFruta()); // Saída: Maçã
    }
}
    

Generics em Métodos

Métodos também podem ter seus próprios parâmetros de tipo, independentes dos tipos genéricos da classe onde estão definidos (se houver).

Sintaxe:

```

// Método com retorno public <T> T metodoComRetorno(T parametro) { ... }

// Método sem retorno public <T> void metodoSemRetorno(T parametro) { ... }

  

Exemplo prático:

 
    ```

public class Maca {
    public <T> T obterDado(T dado) {
        return dado;
    }

    public <T> void imprimirDado(T dado) {
        System.out.println(dado);
    }
}
    

Teste:

```

public class TesteGenerics { public static void main(String[] args) { Maca maca = new Maca(); maca.imprimirDado(123); // Saída: 123 System.out.println(maca.obterDado("texto")); // Saída: texto } }

  

### Generics em Interfaces

Assim como em classes, interfaces podem ser definidas com parâmetros de tipo, comumenet nomeados como `T`.

Definição:

 
    ```

public interface NomeInterface<T, A, B, C> {
    T metodo1();
}
    

Ao implementar uma interface genérica, você pode fornecer os tipos concretos ou deixar a implementação genérica.

Implementação com tipo concreto:

```

public class MinhaClasse implements NomeInterface<TipoConcreto1, TipoConcreto2, TipoConcreto3> { @Override public TipoConcreto1 metodo1() { // implementação } }

  

Implementação mantendo a generalidade (a classe que implementa também se torna genérica):

 
    ```

public class MinhaClasse<T> implements NomeInterface<T> {
    @Override
    public T metodo1() {
        // implementação
    }
}
    

Restrições em Generics (Wildcards)

Restrições podem ser aplicadas a parâmetros de tipo para limitar os tipos que podem ser usados.

  • Upper Bound (Limite Superior): Restringe o tipo genérico a uma classe específica ou suas subclasses. Sintaxe: <T extends ClasseOuInterface>.
  • Lower Bound (Limite Inferior): Restringe o tipo genérico a uma classe específica ou suas superclasses. Sintaxe: <T super ClasseOuInterface>.

Wildcards em Generics

Wildcards (?) são usados para indicar um tipo desconhecido ou para aplicar restrições de limite superior/inferior em um contexto específico, como em parâmetros de métodos ou atribuições.

Exemplo ilustrando limites superior e inferior:

```

public class ExemploWildcard { public static void main(String[] args) { // Limite superior: ? aceita classes que são subtipos de Desperdicio Lixeira<? extends Desperdicio> lixeira1 = new Lixeira<ResiduoMedico>(); Lixeira<? extends Desperdicio> lixeira2 = new Lixeira<ResiduoOrganico>();

    // Limite inferior: ? aceita classes que são supertipos de ResiduoOrganico
    Lixeira<? super ResiduoOrganico> lixeira3 = new Lixeira<Desperdicio>();
    Lixeira<? super ResiduoOrganico> lixeira4 = new Lixeira<ResiduoOrganico>();
}

}

interface Desperdicio {}

interface NaoReciclavel extends Desperdicio {}

class Lixeira<T, C> { // ... implementação }

class ResiduoMedico implements NaoReciclavel { }

class ResiduoOrganico implements NaoReciclavel { }

  

Tags: java generics Tipos Parametrizados wildcards Limite Superior

Publicado em 6-21 18:40