The Java™ Tutorials — Generics :Unbounded Wildcards 非受限通配符
原文地址:https://docs.oracle.com/javase/tutorial/java/generics/unboundedWildcards.html
关键点
- 两个关键使用场合:
- 写一个方法,而这方法的实现可以利用Object类中提供的功能时
- 泛型类中的方法不依赖类型参数时
- 如List.size()方法,它并不关心List中元素的具体类型
List<XXX>
是List<?>
的一个子类型- 理解
List<Object>
和List<?>
的不同:差在NULL处理,前者不支持,而后者却可接受一个null入表
全文翻译
The unbounded wildcard type is specified using the wildcard character (?), for example, List<?>. This is called a list of unknown type. There are two scenarios where an unbounded wildcard is a useful approach:
- If you are writing a method that can be implemented using functionality provided in the Object class.
- When the code is using methods in the generic class that don’t depend on the type parameter. For example, List.size or List.clear. In fact,
Class<?>
is so often used because most of the methods inClass<T>
do not depend on T.
非受限通配符是由一个泛型符号“?”指定的。例如List<?>,它名为一种未知元素类型的列表。这里有非受限通配符非常适用的两种场合:
- 如果你在写一个方法,而这方法的实现可以利用Object类中提供的功能时
- 当代码正在使用泛型类中的方法,而不依赖类型参数时。例如,List.size()方法和List.clear()方法。事实上,
Class<?>
的使用也十分常见,因为Class<T>
中的大部分方法并不依赖于泛型参数T。
Consider the following method, printList:
考虑下下面的printList方法:
public static void printList(List<Object> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
The goal of printList is to print a list of any type, but it fails to achieve that goal — it prints only a list of Object instances; it cannot print
List<Integer>
,List<String>
,List<Double>
, and so on, because they are not subtypes ofList<Object>
. To write a generic printList method, useList<?>
:
printList方法的目标是打印出任何类型的列表,但是这么写是达不到目的的——它仅仅打印出了元素类型为Object的列表;它无法打印List<Integer>
,List<String>
和List<Double>
等等。因为这些类型都不是List<Object>
的子类。为了写出通用的printList方法,你需要使用List<?>
:
public static void printList(List<?> list) {
for (Object elem: list)
System.out.print(elem + " ");
System.out.println();
}
Because for any concrete type A,
List<A>
is a subtype ofList<?>
, you can use printList to print a list of any type:
需要这么写的原因,是对于任何具体类型A,List<A>
是List<?>
的子类型。此时你就可以利用printList()方法来打印任何类型的列表了:
List<Integer> li = Arrays.asList(1, 2, 3);
List<String> ls = Arrays.asList("one", "two", "three");
printList(li);
printList(ls);
Note: The Arrays.asList method is used in examples throughout this lesson. This static factory method converts the specified array and returns a fixed-size list.
注意:Arrays.asList方法的使用会贯穿本课时。这个静态工厂方法会将任何指定的具体数组转化为了一个固定大小的列表。
It’s important to note that
List<Object>
andList<?>
are not the same. You can insert an Object, or any subtype of Object, into aList<Object>
. But you can only insert null into aList<?>
. The Guidelines for Wildcard Use section has more information on how to determine what kind of wildcard, if any, should be used in a given situation.
明确List<Object>
和List<?>
并不同是十分重要的。你可插入一个Object或是任何Object的子类型到一个List<Object>
中。但是你可以将一个null传入到List<?>
中。《通配符使用指南》中会有关于如何在给定情况下决定使用哪种通配符(如果有多种可选项的话)的更多信息。