Java 泛型

泛型方法、泛型类、类型通配符与类型擦除。

Intermediate
Key Points泛型把类型检查提前到编译期;`? extends T` 只读、`? super T` 只写;运行时类型被擦除。

泛型方法

Declare <T> before the return type and the compiler infers it at the call site. One method then works safely for many types with no casts and no ClassCastException.

Java
public class GenericMethod {
    static <T> void print(T value) {
        System.out.println(value);
    }

    static <T extends Comparable<T>> T max(T a, T b) {
        return a.compareTo(b) >= 0 ? a : b;
    }

    public static void main(String[] args) {
        print("text");
        print(42);

        System.out.println(max(3, 7));
        System.out.println(max("apple", "banana"));
    }
}
Output
text
42
7
banana

泛型类

class Box<T> makes the whole class generic. T is convention for Type, with E for Element and K/V for Key/Value. Generics require wrapper types, not primitives.

Java
class Box<T> {
    private T value;

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

    T get() {
        return value;
    }
}

public class GenericClass {
    public static void main(String[] args) {
        Box<String> b = new Box<>();
        b.set("hello");
        System.out.println(b.get());

        Box<Integer> n = new Box<>();
        n.set(100);
        System.out.println(n.get() + 1);
    }
}
Output
hello
101

类型通配符

? extends T means T or a subtype — such a collection can be read but not written safely. ? super T means T or a supertype — writable, but reads only give Object.

Java
import java.util.ArrayList;
import java.util.List;

public class Wildcard {
    static double sum(List<? extends Number> nums) {
        double total = 0;
        for (Number n : nums) {
            total += n.doubleValue();
        }
        return total;
    }

    static void addInts(List<? super Integer> list) {
        list.add(1);
        list.add(2);
    }

    public static void main(String[] args) {
        System.out.println(sum(List.of(1, 2, 3)));
        System.out.println(sum(List.of(1.5, 2.5)));

        List<Number> target = new ArrayList<>();
        addInts(target);
        System.out.println(target);
    }
}
Output
6.0
4.0
[1, 2]

类型擦除

Generics exist only at compile time: after erasure List<String> and List<Integer> are both List. Hence no new T(), no T.class and no direct generic arrays.

Java
import java.util.ArrayList;
import java.util.List;

public class Erasure {
    public static void main(String[] args) {
        List<String> a = new ArrayList<>();
        List<Integer> b = new ArrayList<>();

        System.out.println(a.getClass() == b.getClass());
        System.out.println(a.getClass().getSimpleName());

        List raw = a;
        raw.add(123);
        System.out.println(raw.size());
    }
}
Output
true
ArrayList
1
The last block bypasses checks with a raw type; nothing fails immediately, but reading it back as a String throws ClassCastException later — exactly what generics eliminate.

Friends & Partners