Java 泛型、对象和通配符的区别和说明

Java generics, objects and wildcards differences & clarifications

我想了解这个概念:

  1. T 对象 - 通用,将被擦除为实际类型。
  2. ?对象-将被擦除成什么?
  3. Object 对象;

T?Object有什么区别?

我很容易理解#1,但是呢:

Object var;
? var;

两者有什么区别?我读到我不能像 T 或任何其他变量那样显式使用 ?,并且 ? 与对象相关,而不是类型。
但实际原因是什么?为什么我不能只写 List 个对象 (List<Object>) 而不是 List 个通配符 (List<?>)?因为我不知道这两种情况下的对象类型。
另外,我想知道 ? 的擦除是什么?

我将列出 T? 之间的主要区别:

  • 基本:T是类型参数,?是通配符。

  • 含义:T在定义泛型时用作类型参数class。当您实例化泛型 class 时,T 将被替换为具体类型。 另一方面,当我们想要引用 unknown 类型参数时,我们使用 ?

  • 定义的地方:如果定义泛型方法,需要在class或方法的顶部声明T。您可以在任何地方使用 ? .
  • 映射:每次使用T都映射到同一个类型(在同一个class中)。每次使用 ? 都可以映射到不同的类型。
  • 对象实例化:您可以使用通用参数 T 创建对象,例如 new ArrayList<T>()。您不能实例化对象,只能实例化 pointers with ?.
  • 集合更新:您可以将对象添加到 T 类型的集合中。您不能将对象添加到类型为 ? 的集合中(因为您不知道它的类型)。

  • 类型擦除:对于泛型,类型擦除适用于 use 泛型。当使用泛型时,它们被转换为 compile-time 检查和 execution-time 强制转换。因此,如果您有以下代码,例如:List<String> myList = new ArrayList<String>();,然后您希望添加到您的列表中,那么您可以执行 myList.add("Hello World"); 然后您想要 get 您刚刚添加的项目,方法是执行 String myString = myList.get(0); 然后编译器会将您的代码编译为 List myList = new ArrayList();String myString = (String) myList.get(0);add 保持不变,原因很明显)。
    所以基本上,在执行时 没有办法 发现 T 本质上是列表对象的 String(该信息已消失)。

    现在对于通配符来说,情况就不同了。通配符 (?) 被 Object 替换(因为它是 无界的 )。这不是很有用。在 build-time 处,编译器将检查您 调用 Object 的行为。如果你有类似 ? extends Foo 的东西,那么 ? 被替换为它的绑定 Foo (在 build-time 编译器将检查你是否只传递 Foo 或任何它的子类型(从 Foo 继承的类型)作为参数)。

?Object & TObject的区别可以分别看here and here