区别? (通配符)和Java中的Type参数

有人可以解释一下这两种方法之间的区别吗? 它们一样吗? 就他们解决的问题而言,他们看起来和我一样。 如果它们相同,为什么需要?

方法#1,无界限

 public static void printList(List list) { for (Object elem : list) System.out.println(elem + " "); System.out.println(); } 

方法#2,无界:

 public static  void printList(List list) { for (Object elem : list) System.out.println(elem + " "); System.out.println(); } 

方法#1,有界

 public static void printList(List list) { for (Object elem : list) System.out.println(elem + " "); System.out.println(); } 

方法#2,有界:

 public static  void printList(List list) { for (Object elem : list) System.out.println(elem + " "); System.out.println(); } 

它们是相同的,因为它们接受相同的参数类型。

但是,使用T (或其他)识别类型可以让您在其他地方引用类型。

编辑:示例:

您的无界示例未充分利用参数化类型的function。 你有:

 public static  void printList(List list) { for (Object elem : list) System.out.println(elem + " "); System.out.println(); } 

这对于打印字符串表示的示例就足够了,但考虑到这一点(非常人为,并且没有error handling):

 public static  T getSecondItem (List list) { T item = list.get(1); return item; } 

返回类型是T,它允许您安全地执行这样的操作,使用编译时类型检查:

 class MyClass { public void myMethod () { } } void somewhere () { List items = ...; getSecondItem(items).myMethod(); } 

命名类型还允许您在多个位置共享相同的类型约束,例如:

 public  int compareLists (List a, List b) { ... } 

如果没有为类型命名,则无法指定ab是相同列表类型的约束(您可以使用List以获得更大的灵活性)。

你还问过“我为什么需要??”。 真正的答案是:你没有。 我想,这主要是为了美学。 Java致力于成为一种精确且无杂乱的语言。 在许多情况下,您根本不关心您所指的类型。 在那些情况下,你可以使用? 没有使用未使用的类型参数声明的代码混乱。

在您的示例中,完全没有任何区别。 每个都会产生相同的输出。

generics的最佳使用和解释要求您了解类型参数的语义以及有关参数角色的信息。 这样做的原因是,在上面的第一个例子(无界外卡)的情况下,语义是“未知类型的对象列表”和“将产生(不消耗) List实例的参数。

上面的方法只生成每个List对象并在每个上调用toString() 。 所有对象都保证有一个toString()方法,因此没有必要为此目的了解对象的类型。 这正是无界通配符是此方法参数的最佳选择的原因:要生成List实例并对它们调用toString() ,不必了解对象的类型。

注意,如果? 具有相同的语义(“未知类型的对象列表”)但具有不同的目的(“List将使用未知类型的对象”)事物会非常非常彻底地改变,以至于它可能是不可取的(或非常困难)使用通配符参数(至少没有辅助方法来捕获对象的类型)。

通常不可能为所有情况断言一个通用参数forms。 使用的最佳forms(通配符与具体;有界与无界;扩展与超级)取决于类型参数的语义以及方法中参数的作用。

如上所述, ? 声明通用代码不需要对类型的任何引用。 正如Java Trails中所指出的,这可能是一个类,其中属性独立于任何类型,如集合的长度。

另一个原因是? 这是因为当通用代码只需要类Object提供的行为时,它为不太模糊的语法提供了语法。 如上所述,参数类型可以工作,但T被定义然后从未使用的事实可能表明开发人员遗漏了一些东西。

因此,如果由于语义歧义而忽略并且不可用,那么开发人员会想要编写 。 但是,这不允许将通用代码用于任何类型,只允许使用Object类型。

所以, 更精确。