我正在努力使用Java 8通配符泛型。
假设一个名为Pair<T>
的通用类(来自Core Java书)
class Pair<T> {
private T first;
private T second;
public Pair() {
first = null;
second = null;
}
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() { return first; }
public T getSecond() { return second; }
public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}
假定以下类层次结构:
基本雇员(层次结构顶部),然后
经理扩展员工,然后
行政人员扩展经理
下面的代码可以工作,但我不明白为什么允许这样做。
Pair<? super Manager> pm2 =
new Pair<>(
new Employee(1,"Yuri"), // Employee is super of Manager
new Executive()); // Executive is not super of Manager
// why Executive is allowed in above Pair<T> ?
Employee ex1 = (Employee) pm2.getFirst(); // OK
Manager ex2 = (Manager) pm2.getSecond(); // OK
Executive ex3 = (Executive) pm2.getSecond(); // why is allowed?
我不理解执行程序为什么不是上面提到的工作,因为它不是管理器的超级类型,而是管理器的子类型。
是因为Java 8编译器转换了吗?超级管理员到对象,因此可以允许任何操作吗?
答案 0 :(得分:1)
您声明的是:
Pair<? super Manager> pm2 = ...
接受泛型的Pair
方法可以用Manager
和该类的子类(在您的情况下为Executive
)代替泛型。
从逻辑上讲,当您使用泛型调用方法时,将得到以下结果:
Pair<? super Manager> pm2 = ...;
pm2.setFirst(new Executive()); // compile
pm2.setFirst(new Manager()); // compile
pm2.setFirst(new Employee()); // doesn't compile
最后,就像您没有使用任何通配符一样:
Pair<Manager> pm2 = ...;
pm2.setFirst(new Executive()); // compile
pm2.setFirst(new Manager()); // compile
pm2.setFirst(new Employee()); // doesn't compile
因此在您的示例中,您使用的下界通配符是无助的。
实际上,这是最糟糕的情况,因为您同时使用它来从泛型类型中放入和获取事物,而下界通配符旨在放入而不是从中获取事物。
而您必须执行的转换却违反了通用目的(类型安全):
Employee ex1 = (Employee) pm2.getFirst(); // OK
Manager ex2 = (Manager) pm2.getSecond(); // OK
Executive ex3 = (Executive) pm2.getSecond(); // why is allowed?
那么我们该如何使用Pair<? super Manager>
?
我们希望可以将通用集合Pair
分配给其他Pair
类型,以将事物“放入”。
最常见的用例是声明一个接受通用类型<? super>
的方法。
但是在这种情况下,我们希望将未知类型限制为特定类型或父类型,以防止“放入”可能损害作为参数传递的泛型类型的类型安全的事物。
例如,假设您需要一个方法,该方法接受Pair
个实例中的Manager
个并将其放入此Pair
中。
您不希望客户方法可以传递Pair<Executive>
,否则如果我们添加Manager
可能会破坏通用安全性,因为Manager
不一定是Executive
实例。这是下界通配符的主要作用。
示例代码说明:
public void putStuff(Pair<? super Manager> managers) {
if (...){
managers.setFirst(new Manager());
}
else if (...){
managers.setFirst(new Executive());
}
}
对于Manager
泛型类型,现在只能传递Pair
的类型或超类型:
putStuff(new Pair<Manager>(...)); // compile
putStuff(new Pair<Employee>(...)); // compile
putStuff(new Pair<Executive>(...)); // doesn't compile
答案 1 :(得分:0)
在Java中,最高级的类型是java.lang.Object
。换句话说,每个单个类的父类是java.lang.Object
。
通过定义的Pair<? super Manager>
,您标记了Pair类可能持有的通用类型的下限。请参阅文档HERE。
在您的示例中,似乎Executive
也是Employee
的子类型,因此很显然它共享相同的超级类型,并且也共享java.lang.Object
。