什么是泛型?

发布: (2026年2月12日 GMT+8 19:00)
4 分钟阅读
原文: Dev.to

Source: Dev.to

Generics 是在 Java 5 中引入的一项功能,允许创建能够处理不同数据类型的类、接口和方法。它们消除了显式类型转换(cast)的需求,并帮助在编译时检测错误。

在 Java 5 之前,集合把所有元素都当作 Object 处理。这会导致两个问题:

  • 过度强制转换: 每次从列表中取出元素都需要进行 (String) 强制转换。
  • 不安全性: 没有任何机制阻止向本应只包含 String 的列表中插入 Integer,从而在运行时产生错误。
// 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 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.

类型变量

Generics 允许类和方法在多种类型的对象上操作,确保编译时安全(compile‑time safety)。约定上,我们使用大写字母来表示这些泛型类型:

  • T: Type(类型)
  • E: Element(元素,常用于集合)
  • K, V: Key, Value(键、值,常用于映射)

泛型类

泛型类使用 类型参数 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);
    }
}

T 在创建对象时会被 StringInteger 或其他类型替代。

通配符

Os wildcards (?) 代表在泛型中未知的类型,并且对于创建接受不同集合类型的方法非常有用。

  • ? – 任意类型。
  • ? extends T (upper bounded) – 接受 T 或任何 子类型T用法: 当只想 读取 数据时。
  • ? super T (lower bounded) – 接受 T 或任何 父类型T用法: 当想 写入 数据时。

实际示例

import java.util.*;

public class Wildcards {

    // Aceita lista de Number OU QUALQUER SUBTIPO (Integer, Double...)
    // Só consigo LER com segurança (sei que tudo ali é Number)
    public static double somarLista(List 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 inteiros = new ArrayList<>();
        inteiros.add(1);
        inteiros.add(2);

        List 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));
    }
}

Type Erasure

泛型仅供 编译器 使用。编译后,Java 会 擦除(type erasure)所有泛型信息,并用 Object(或上限)替代,同时自动插入强制类型转换。在运行时,ListList 是同一个类(List)。此策略是为了保持与早期 Java 版本的兼容性。

0 浏览
Back to Blog

相关文章

阅读更多 »