为什么 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); }