为什么 Java 的泛型类型不能用于静态方法?

来看个例子:

class Pair<T> {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { return this.first; }
    public T getLast() { return this.last; }

    // 对静态方法使用<T>:
    public static Pair<T> create(T first, T last) {
        return new Pair<T>(first, last);
    }
}

如果在static方法中写泛型,那么编译器会报错。这是因为普通的方法是通过类的实例来调用的,也就是方法必须创建一个实例出来才能调用(也就是new),在创建实例的时候会调用实例的构造方法,这时候创建的实例就能知道这个类上面定义的<T>类型了。

而静态方法呢,不需要创建一个实例就能调用,不创建实例也就没有调用构造方法,那么创建出来的实例就无法 get 到这个类的<T>类型,因此相当于盲人摸象。

看下面的定义:

Pair<String> p = new Pair<>("Hello", "world");  //创建实例时已经知道<T>是String类型
String first = p.getFirst();  

Pair.create(...);  //如果 create 是类 Pair 的静态方法,则并不清楚<T>的具体类型

总结:静态方法由于随着类的加载而加载,不能访问类的泛型(因为在创建对象的时候才确定),因此必须定义自己的泛型类型。

那么怎么让泛型类型适用于静态方法呢?

// 静态 create 泛型方法
public static <T> Pair<T> create(T first, T last) {
    return new Pair<T>(first, last);
}

上面,在 static 后面也加上<T>编译器就不会报错了,但实际上这个<T>Pair<T>类型的<T>已经没有任何关系了。

将静态方法的泛型类型和实例类型的泛型类型区分开:

// 静态 create 泛型方法
// 要这样,K不与类定义的<T>冲突
public static <K> Pair<K> create(K first, K last) {
    return new Pair<K>(first, last);
}