- 由于严格的泛型类型使用不方便,所以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方法。