Skip to content

泛型

泛型不支持基本数据类型(如 intdouble,只能使用引用类型(对象)

泛型擦除

Java 的泛型只存在于编译阶段

java
List<Integer> list = new ArrayList<>();

编译后会变成:

java
List list = new ArrayList();
  • 泛型类型信息在运行时被“擦除”
  • JVM底层使用的是 Object,这是因为早期JDK并没有泛型,添加泛型后需要确保兼容之前的版本

为什么需要泛型

使用泛型之前

java
List list = new ArrayList();
list.add("hello");
list.add(123); // 也能加

String str = (String) list.get(1); // 运行时才报错
  • 类型不安全(什么都能放)
  • 需要强制类型转换
  • 错误发生在运行时

使用泛型之后

java
List<String> list = new ArrayList<>();
list.add("hello");
// list.add(123); // 编译直接报错

String str = list.get(0); // 不需要强转
  • 编译期检查类型
  • 不需要强制转换
  • 代码更清晰

泛型参数

泛型类

java
public class Box<T> {
    private T value;

    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }
}

创建对象时指定泛型参数:

java
Box<String> box = new Box<>();
box.set("hello");
String val = box.get();

泛型方法

泛型参数 <T> 需要写在返回值前面,表示这个方法是一个泛型方法,泛型参数来着方法调用者,而不是来自class

java
public <T> void test(T a, T b) {}

泛型参数根据传入的形参自动推断出类型

java
test(1, 2);       // T = Integer
test("a", "b");   // T = String

泛型接口

java
public interface Converter<T> {
    T convert(String input);
}

实现接口时,指定泛型接口的参数:

java
public class IntegerConverter implements Converter<Integer> {
    public Integer convert(String input) {
        return Integer.valueOf(input);
    }
}

泛型与静态成员

泛型类

静态成员不能使用类的泛型,是因为在泛型类中,泛型属于“对象”,而静态属于“类”

java
public class Test<T> {
    static T value; // ❌ 编译报错
}

泛型类中的泛型是属于实例级别的:

java
Test<String> t1 = new Test<>();
Test<Integer> t2 = new Test<>();

泛型方法

对于泛型方法,泛型属于方法的,因此可以定义一个静态泛型方法