Java Genéricos Intermediário
Genéricos
Genéricos permitem escrever classes, interfaces e métodos que operam sobre tipos parametrizados, garantindo segurança de tipos em tempo de compilação e evitando casts explícitos. Eles foram introduzidos no Java 5 para resolver problemas de ClassCastException em coleções, por exemplo.
Com genéricos, você define uma classe Caixa<T> e pode criar Caixa<String> ou Caixa<Integer>, e o compilador verifica os tipos usados. Isso é possível porque o compilador insere os casts necessários e verifica os tipos em tempo de compilação, mas depois remove as informações de tipo (type erasure), então em tempo de execução não há sobrecarga de performance.
Além disso, você pode restringir os tipos com bounded types (<T extends Number>) e usar wildcards (? extends, ? super) para aumentar a flexibilidade em APIs. Entender esses conceitos é essencial para usar bem as coleções da biblioteca padrão e criar código reutilizável e seguro.
Pontos-chave
- Genéricos permitem parametrizar classes e métodos com tipos, garantindo verificação em tempo de compilação.
- Bounded types restringem o tipo genérico a subtipos de uma classe ou interface, permitindo chamar métodos desse bound.
- Wildcards (
? extends Te? super T) tornam APIs mais flexíveis para leitura e escrita de coleções. - Type erasure remove os parâmetros de tipo em tempo de execução, então não é possível usar
new T()ouinstanceof T. - Métodos genéricos podem ser declarados independentemente da classe, com o parâmetro de tipo antes do retorno.
import java.util.ArrayList;
import java.util.List;
// Classe genérica simples
class Caixa<T> {
private T conteudo;
public void guardar(T item) { this.conteudo = item; }
public T obter() { return conteudo; }
}
public class GenericosDemo {
// Método genérico com bounded type
public static <T extends Number> double soma(List<T> numeros) {
double total = 0;
for (T n : numeros) total += n.doubleValue();
return total;
}
// Wildcard para leitura
public static void imprimir(List<? extends Number> lista) {
for (Number n : lista) System.out.print(n + " ");
System.out.println();
}
public static void main(String[] args) {
Caixa<String> caixaTexto = new Caixa<>();
caixaTexto.guardar("Olá, genéricos!");
System.out.println(caixaTexto.obter());
List<Integer> inteiros = new ArrayList<>();
inteiros.add(10);
inteiros.add(20);
System.out.println("Soma: " + soma(inteiros));
imprimir(inteiros);
List<Double> doubles = List.of(1.5, 2.5, 3.5);
imprimir(doubles);
}
}