List<? extends Number> 最好读作:
这是一个数字列表,但是是协变的。
换句话说,这是一个具体但未知类型的列表。但是,我确实知道,无论它是什么类型,至少它是 Number 或其某个子类。
泛型很奇怪;一旦你选择了一些差异,你就会得到随之而来的限制。在集合的情况下,“协方差”伴随着“不添加”的包袱。
试试看。
g1.add(XXX);
这里唯一对XXX 合法的东西? null。字面意思就是这样。你可以添加到这个东西的完整、完整和详尽的列表。当然 Number x = 5; g1.add(x); 不会在这里被 javac 允许。
写List<? extends a thingie> 你是在说:是的,我想要那个。我正在签署这个限制,我绝对不会添加任何内容(除了文字 null 的学术案例)。作为给自己戴上手铐的交易,你可以传递给g1的东西大大增加了。
您也可以选择逆变:
void foo(List<? super Integer> list) {
list.add(Integer.valueOf(5)); // works!
Integer x = list.get(0); // no go
}
逆变是相反的。添加作品。得到不起作用。在这种情况下,这意味着:表达式list.get(0) 的类型只是.. Object。
现在我们已经介绍了:
void test(List<? extends Number> g1, List<? extends Number> g2) {}
表示“我的第一个参数是一个数字列表,但我选择了协方差手铐”,“我的第二个参数是一个数字列表,但我也为此选择了协方差手铐”,现在有意义了为什么java让你写g1 = g2。 g2 保证是 X<Y>,其中 X 是 List 的某个具体子类,Y 是 Number 或其某个子类。
这是 100% 兼容的,类型方面的,与“某种列表,其类型参数是数字的某种协变形式”的概念。您唯一可以做的事情 List<? extends Number> 是调用 List 的方法,其中签名中的任何 T 对参数都“禁用”,并由绑定替换(Number) 用于返回类型。
这正是List<? extends Number> 所描述的内容,所以它是兼容的。