什么方法声明接受有界和无界多级泛型?



给定:

public class Testcase {
public static <E> List<List<E>> transform(List<List<E>> list) {
return list;
}
public static <E> List<List<? extends E>> transform2(List<List<? extends E>> list) {
return list;
}
public static void main(String[] args) {
List<List<Integer>> known = new ArrayList<>();
List<List<? extends Number>> unknown = new ArrayList<>();
transform(known);    // works
transform(unknown);  // fails
transform2(known);   // fails
transform2(unknown); // works
}
}

编译器接受transform(known)但抱怨:

cannot infer type-variable(s) E
(argument mismatch; List<List<? extends Number>> cannot be converted to List<List<E>>)
where E is a type-variable:
E extends Object declared in method <E>transform(List<List<E>>)

对于transform(unknown).我得到了相反的问题transform2().我已经咨询了PECS,我相信transform()是正确的方法声明,但我无法弄清楚如何获得一种方法来处理这两种情况。

请注意,此问题仅发生在多级泛型上。List<? extends Number>工作得很好。该问题并非特定于列表。你会得到它Future<Task<X>>等等。

什么方法声明将同时处理有界泛型和无界泛型?如果不可能,为什么?

这工作的最具体的类型似乎是? extends List<? extends ?>

class Testcase {
public <E> List<List<E>> transform(List<List<E>> list) {
return list;
}
public <E> List<List<? extends E>> transform2(List<List<? extends E>> list) {
return list;
}
public <E> List<? extends List<? extends E>> transform3(List<? extends List<? extends E>> list) {
return list;
}    
public void test(String[] args) {
List<List<Integer>> known = new ArrayList<>();
List<List<? extends Number>> unknown = new ArrayList<>();
transform(known);    // works
// transform(unknown);  // fails
// transform2(known);   // fails
transform2(unknown); // works
transform3(known);
transform3(unknown);
}
}

以下是为什么这是有意义的解释。

List<? extends Number>显然不是任何EList<E>,因为它不必能够插入最一般E的实例,因此第一个定义失败。

List<Integer>符合List<? extends Number>,但这无济于事,因为这些类型仍然不相等,因此类型List<List<Integer>>List<List<? extends Number>>是完全不相关的。因此,第二个定义也失败了。

相反,您想要的是List<List<Integer>>List<List<? extends Number>>的使用站点最小上限。您可以使用以下规则获取它:List<A>List<B>的使用站点 LUB 为:

USLUB(List<A>, List<B>) = List<? extends USLUB(A, B)>

现在,一步一步:

  1. 对于A = IntegerB = ? extends Number,最小上限是? extends Number,因为Integer符合? extends Number
  2. 对于List<Integer>List<? extends Number>,最小上限变为? extends List<? extends Number>
  3. 因此,最终结果是List<? extends List<? extends Number>>.

为使用站点差异;)欢呼

最新更新