gpt4 book ai didi

java - 泛型、类型参数和通配符

转载 作者:IT老高 更新时间:2023-10-28 20:47:43 25 4
gpt4 key购买 nike

我正在尝试理解 Java 泛型,但它们似乎非常难以理解。比如这样就可以了……

public class Main {

public static void main(String[] args) {
List<?> list = null;
method(list);
}

public static <T> void method(List<T> list) { }
}

……原来如此……

public class Main {

public static void main(String[] args) {
List<List<?>> list = null;
method(list);
}

public static <T> void method(List<T> list) { }
}

...还有这个...

public class Main {

public static void main(String[] args) {
List<List<List<?>>> list = null;
method(list);
}

public static <T> void method(List<List<T>> list) { }
}

...但这不能编译:

public class Main {

public static void main(String[] args) {
List<List<?>> list = null;
method(list);
}

public static <T> void method(List<List<T>> list) { }
}

有人可以用简单的语言解释发生了什么吗?

最佳答案

了解泛型类型的主要内容是它们不是协变的。

所以虽然你可以这样做:

final String string = "string";
final Object object = string;

以下将无法编译:

final List<String> strings = ...
final List<Object> objects = strings;

这是为了避免绕过泛型类型的情况:

final List<String> strings = ...
final List<Object> objects = strings;
objects.add(1);
final String string = strings.get(0); <-- oops

所以,一个一个地浏览你的例子

1

您的通用方法采用 List<T> , 你传入一个 List<?> ; (基本上)是 List<Object> . T可以分配到Object类型和编译器很高兴。

2

你的泛型方法是一样的,你传入一个List<List<?>> . T可以分配到List<?>输入,编译器又高兴了。

3

这与 2 基本相同,只是多了一层嵌套。 T仍然是List<?>输入。

4

这是一个有点梨形的地方,也是我从上面的观点进来的地方。

您的通用方法采用 List<List<T>> .你传入一个 List<List<?>> .现在,由于泛型类型不是协变的,List<?>不能分配给 List<T> .

实际的编译器错误(Java 8)是:

required: java.util.List<java.util.List<T>> found: java.util.List<java.util.List<?>> reason: cannot infer type-variable(s) T (argument mismatch; java.util.List<java.util.List<?>> cannot be converted to java.util.List<java.util.List<T>>)

基本上编译器告诉你它找不到T分配,因为必须推断 List<T> 的类型嵌套在外部列表中。

让我们更详细地看一下:

List<?>List 某种未知类型 - 它可能是 List<Integer>List<String> ;我们可以get从它作为Object , 但我们不能add 。因为否则我们会遇到我提到的协方差问题。

List<List<?>>ListList一些未知类型的 - 它可能是 List<List<Integer>>List<List<String>> .在 1 的情况下,可以分配 TObject只是不允许add通配符列表上的操作。如果 4 无法做到这一点 - 主要是因为没有泛型构造来防止 add到外部List .

如果编译器要分配 TObject在第二种情况下,可能会出现以下情况:

final List<List<Integer>> list = ...
final List<List<?>> wildcard = list;
wildcard.add(Arrays.asList("oops"));

因此,由于协方差,无法分配 List<List<Integer>> 任何其他通用List安全。

关于java - 泛型、类型参数和通配符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27465348/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com