• 由于严格的泛型类型使用不方便,所以Java的设计者发明了一种巧妙但很安全的“解决方案”:通配符类型

通配符概念

在通配符类型中,允许类型参数发生变化。例如通配符类型Pair<? extends Employee>

表示任何泛型Pair类型,它的类型参数是Employee的子类,如Pair<Manager>

假设有一个方法public static void printBuddies(Pair<Employee> p),那么就不能将Pair传递给这个方法。

解决方法就是,使用一个通配符类型:public static void printBuddies(Pair<? extends Employee> p)

类型Pair<Manager>Pair<? extends Employee>的子类。

Pair<? extends Employee>的方法如下:

? extend Employee getFirst(); // 可以使用getFirst,将getFirst的返回值赋给一个Employee引用是完全合法的
void setFirst(? extends Employee); // 不可能调用setFirst方法,因为编译器只知道需要Employee的某个子类,但不知道什么类型。所以拒绝传递任何特定的类型,比较?不能匹配

通配符的超类型限定

可以指定一个超类型限定,如下所示:? super Manager

这个通配符限制为Manager的所有超类。

带有超类限定的通配符和带有子类限定的通配符的行为相反,可以为方法提供参数,但是不能使用返回值。例如Pair<? super Manager>的方法如下:

void setFirst(? super Manager); // 编译器无法知道setFirst方法的具体类型,因此不能接受参数类型为Employee或者Object的方法调用。只能传递Manager类型的对象,或者某个子类对象
? super Manager getFirst(); // 不能保证返回对象的类型,只能把它赋给一个Object
带有超类限定的通配符允许你写入一个泛型对象,而带有子类限定的通配符允许你读取一个泛型对象

无限定通配符

例如,类型Pair<?>,有以下方法:

? getFirst(); // getFirst返回值只能赋给一个Object。
void setFirst(?); // setFirst方法不能被调用,甚至不能用Object调用。
Pair<?>和Pair本质不同在于:可以用任意Object对象调用原始Pair类的setFirst方法。