什么方法声明接受有界和无界的多级泛型?
What method declaration accepts bounded and unbounded multi-level Generics?
鉴于:
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);
}
}
这里解释了为什么这是有道理的。
A List<? extends Number>
显然不是任何 E
的 List<E>
,因为它不必能够插入最一般的 E
的实例,因此第一个定义失败。
A List<Integer>
符合 List<? extends Number>
,但这没有帮助,因为这些类型仍然不相等,因此类型 List<List<Integer>>
和 List<List<? extends Number>>
完全无关。因此,第二个定义也失败了。
您想要的是 List<List<Integer>>
和 List<List<? extends Number>>
的 use-site 最小上限。您可以使用以下规则获得它: List<A>
和 List<B>
的 use-site-LUB 是:
USLUB(List<A>, List<B>) = List<? extends USLUB(A, B)>
现在,一步一步:
- 对于
A = Integer
和B = ? extends Number
,最小上界是? extends Number
,因为Integer
符合? extends Number
.
- 对于
List<Integer>
和List<? extends Number>
,最小上限变为? extends List<? extends Number>
- 所以最后的结果是
List<? extends List<? extends Number>>
.
为 use-site 方差欢呼 ;)
鉴于:
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);
}
}
这里解释了为什么这是有道理的。
A List<? extends Number>
显然不是任何 E
的 List<E>
,因为它不必能够插入最一般的 E
的实例,因此第一个定义失败。
A List<Integer>
符合 List<? extends Number>
,但这没有帮助,因为这些类型仍然不相等,因此类型 List<List<Integer>>
和 List<List<? extends Number>>
完全无关。因此,第二个定义也失败了。
您想要的是 List<List<Integer>>
和 List<List<? extends Number>>
的 use-site 最小上限。您可以使用以下规则获得它: List<A>
和 List<B>
的 use-site-LUB 是:
USLUB(List<A>, List<B>) = List<? extends USLUB(A, B)>
现在,一步一步:
- 对于
A = Integer
和B = ? extends Number
,最小上界是? extends Number
,因为Integer
符合? extends Number
. - 对于
List<Integer>
和List<? extends Number>
,最小上限变为? extends List<? extends Number>
- 所以最后的结果是
List<? extends List<? extends Number>>
.
为 use-site 方差欢呼 ;)