Generics
Generics tornam o código mais seguro e flexível. Esta lição cobre o uso de generics em Java.
O que são Generics
Generics são tipos parametrizados que permitem que classes e métodos trabalhem com múltiplos tipos.
Benefícios dos Generics
| Benefício | Descrição |
|---|---|
| Segurança de tipo | Verificação de tipo em tempo de compilação |
| Reutilização de código | Um código funciona com múltiplos tipos |
| Eliminar casting | Não é necessária conversão manual de tipos |
Classes Genéricas
Sintaxe
public class NomeDaClasse<T> {
// Usar T como tipo
}
Exemplo: Classe Genérica
public class Box<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
public static void main(String[] args) {
// Armazenar Integer
Box<Integer> intBox = new Box<>();
intBox.set(100);
int num = intBox.get(); // Sem casting necessário
// Armazenar String
Box<String> strBox = new Box<>();
strBox.set("Hello");
String str = strBox.get();
System.out.println("Box Integer: " + num);
System.out.println("Box String: " + str);
}
}
Múltiplos Parâmetros Genéricos
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
@Override
public String toString() {
return key + "=" + value;
}
public static void main(String[] args) {
Pair<String, Integer> pair = new Pair<>("Alice", 95);
System.out.println(pair); // Alice=95
}
}
Métodos Genéricos
Sintaxe
public static <T> nomeMetodo(parâmetros) {
// Usar T
}
Exemplo: Métodos Genéricos
public class GenericMethod {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
public static <T> T getFirst(T[] array) {
if (array == null || array.length == 0) {
return null;
}
return array[0];
}
public static <T extends Comparable<T>> T getMax(T[] array) {
T max = array[0];
for (T element : array) {
if (element.compareTo(max) > 0) {
max = element;
}
}
return max;
}
public static void main(String[] args) {
Integer[] nums = {1, 2, 3, 4, 5};
String[] names = {"Alice", "Bob", "Charlie"};
printArray(nums); // 1 2 3 4 5
printArray(names); // Alice Bob Charlie
System.out.println("Primeiro número: " + getFirst(nums)); // 1
System.out.println("Primeiro nome: " + getFirst(names)); // Alice
System.out.println("Máximo: " + getMax(nums)); // 5
System.out.println("Nome máximo: " + getMax(names)); // Charlie
}
}
Interfaces Genéricas
Definindo Interface Genérica
public interface Repository<T> {
void add(T item);
T get(int index);
List<T> getAll();
}
Implementando Interface Genérica
public class ArrayListRepository<T> implements Repository<T> {
private List<T> list = new ArrayList<>();
@Override
public void add(T item) {
list.add(item);
}
@Override
public T get(int index) {
return list.get(index);
}
@Override
public List<T> getAll() {
return new ArrayList<>(list);
}
public static void main(String[] args) {
Repository<String> repo = new ArrayListRepository<>();
repo.add("Alice");
repo.add("Bob");
System.out.println(repo.getAll()); // [Alice, Bob]
}
}
Curingas Genéricos
Curinga Não Limitado ?
public static void printList(List<?> list) {
for (Object item : list) {
System.out.println(item);
}
}
Curinga Superior Limitado ? extends T
// Aceita apenas Number e suas subclasses
public static double sum(List<? extends Number> list) {
double total = 0;
for (Number num : list) {
total += num.doubleValue();
}
return total;
}
Curinga Inferior Limitado ? super T
// Aceita apenas Integer e suas superclasses
public static void addNumbers(List<? super Integer> list) {
list.add(1);
list.add(2);
list.add(3);
}
Exemplo: Curingas
import java.util.ArrayList;
import java.util.List;
public class WildcardDemo {
// Curinga não limitado
public static void printList(List<?> list) {
for (Object item : list) {
System.out.print(item + " ");
}
System.out.println();
}
// Curinga superior limitado
public static double sum(List<? extends Number> list) {
double total = 0;
for (Number num : list) {
total += num.doubleValue();
}
return total;
}
public static void main(String[] args) {
List<Integer> ints = new ArrayList<>();
ints.add(1);
ints.add(2);
ints.add(3);
List<String> strs = new ArrayList<>();
strs.add("Alice");
strs.add("Bob");
printList(ints); // 1 2 3
printList(strs); // Alice Bob
System.out.println("Soma: " + sum(ints)); // 6.0
}
}
Type Erasure
Generics em Java são implementados através de type erasure—informações genéricas são apagadas após a compilação.
// Antes da compilação
List<String> list = new ArrayList<>();
list.add("Hello");
// Depois da compilação (type erasure)
List list = new ArrayList();
list.add("Hello");
String str = (String) list.get(0); // Casting automático
List<String> e List<Integer> são o mesmo tipo em tempo de execução.
Restrições Genéricas
Exemplo: Generics Limitados
// T deve implementar Comparable
public static <T extends Comparable<T>> T min(T a, T b) {
return a.compareTo(b) <= 0 ? a : b;
}
// T deve ser uma subclasse de Number
public static <T extends Number> double doubleValue(T num) {
return num.doubleValue();
}
Nomes Comuns de Generics
| Nome | Significado |
|---|---|
T |
Type (Tipo) |
E |
Element (Elemento) |
K |
Key (Chave) |
V |
Value (Valor) |
N |
Number (Número) |
❓ Perguntas Frequentes
P: Por que usar generics? R: Segurança de tipo, reutilização de código e eliminação de casting.
P: Generics suportam tipos primitivos? R: Não, use classes wrapper. Por exemplo,
List<int>deve serList<Integer>.
P: Qual é a diferença entre
<?>e<Object>? R:<?>é tipo desconhecido—só pode ler, não escrever.<Object>é tipo Object—pode ler e escrever.
📖 Resumo
- Generics tornam o código mais seguro e flexível
- Classes genéricas, métodos genéricos, interfaces genéricas
- Curingas:
?,? extends,? super - Type erasure: informações genéricas são apagadas após a compilação
📝 Exercícios
- Contêiner genérico: Implemente uma classe Stack genérica
- Método genérico: Implemente um método genérico para converter array em List
- Generics limitados: Implemente um método para comparar dois objetos
Próxima Lição
Na próxima lição, aprenderemos sobre Prática: Aplicações de Coleções — aplicando conhecimentos de coleções.



