DEV Community

Alex Reis
Alex Reis

Posted on

O que são generics?

Generics são uma funcionalidade introduzida no Java 5 que permite criar classes, interfaces e métodos que trabalham com diferentes tipos de dados. Eles eliminam a necessidade de conversões explícitas (casts) e ajudam a detectar erros em tempo de compilação.

Antes do Java 5, as coleções tratavam tudo como Object. Isso gerava dois problemas:

  1. Casting Excessivo: Você tinha que fazer cast (String) toda vez que tirava algo da lista.
  2. Insegurança: Nada impedia você de colocar um Integer numa lista que deveria ser só de String. O erro só estourava na cara do usuário (Runtime).
// Código antigo
List lista = new ArrayList(); // Lista "crua" (Raw Type)
lista.add("Olá");
lista.add(10); // O compilador deixa passar!

// O erro só acontece AQUI, quando o programa está rodando:
String texto = (String) lista.get(1); // ClassCastException!

// Código novo com Generics
List<String> lista = new ArrayList<>();
lista.add("Olá");
// lista.add(10); // O compilador NEM DEIXA compilar. Erro na hora!

String texto = lista.get(0); // Sem necessidade de cast manual.
Enter fullscreen mode Exit fullscreen mode

Variáveis de tipo

Generics permitem que classes e métodos operem em objetos de vários tipos, garantindo a segurança em tempo de compilação (Compile-time safety).

Usamos letras maiúsculas por convenção para representar esses tipos genéricos:

  • T: Type (Tipo genérico)
  • E: Element (usado em Collections)
  • K, V: Key, Value (usado em Maps)

Classe Genérica

Uma classe genérica utiliza um parâmetro de tipo representado por <T>, que funciona como um placeholder para o tipo real.

// <T> define que esta classe aceita um parâmetro de tipo
public class Caixa<T> {
    private T conteudo;

    public void guardar(T conteudo) {
        this.conteudo = conteudo;
    }

    public T abrir() {
        return conteudo;
    }
}

public class AulaGenerics {
    public static void main(String[] args) {
        // Caixa que só aceita Strings
        Caixa<String> caixaDeTexto = new Caixa<>();
        caixaDeTexto.guardar("Segredo");
        // caixaDeTexto.guardar(123); // Erro de compilação!

        // Caixa que só aceita Inteiros
        Caixa<Integer> caixaDeNumeros = new Caixa<>();
        caixaDeNumeros.guardar(100);
    }
}
Enter fullscreen mode Exit fullscreen mode
  • <T> é substituído por String ou Integer no momento da criação do objeto.

Wildcards

Os wildcards (?) são usados para representar tipos desconhecidos em generics. Eles são úteis para criar métodos que aceitam diferentes tipos de coleções.

  • <?>: Qualquer coisa.
  • <? extends T> (Upper Bounded): Aceita T ou qualquer filho de T.
    • Uso: Quando você quer apenas LER dados (Get).
  • <? super T> (Lower Bounded): Aceita T ou qualquer pai de T.
    • Uso: Quando você quer ESCREVER dados (Add).

Exemplo Prático

public class Wildcards {

    // Aceita lista de Number OU QUALQUER FILHO (Integer, Double...)
    // Só consigo LER com segurança (sei que tudo ali é Number)
    public static double somarLista(List<? extends Number> lista) {
        double soma = 0;
        for (Number n : lista) { // Posso ler como Number
            soma += n.doubleValue();
        }
        // lista.add(10); // ERRO! Não posso adicionar nada (não sei se é lista de Double ou Integer)
        return soma;
    }

    public static void main(String[] args) {
        List<Integer> inteiros = new ArrayList<>();
        inteiros.add(1);
        inteiros.add(2);

        List<Double> doubles = new ArrayList<>();
        doubles.add(1.5);
        doubles.add(2.5);

        // O método aceita ambos!
        System.out.println(somarLista(inteiros));
        System.out.println(somarLista(doubles));
    }
}
Enter fullscreen mode Exit fullscreen mode

Type Erasure

Generics só existem para o Compilador. Depois que o código vira .class (Bytecode), o Java apaga todas as informações de Generics e substitui por Object (ou pelo limite superior) e insere os casts automaticamente.

Isso significa que, em tempo de execução, List<String> e List<Integer> são a mesma classe (List). Isso foi feito para manter compatibilidade com versões antigas do Java.

Top comments (0)