|
7 | 7 |
|
8 | 8 | **实例创建**在类实例创建表达式中,如果类型是参数化类型,则没有任何类型参数可能是通配符。 例如,以下是非法的:
|
9 | 9 |
|
10 |
| - ```java |
11 |
| - List<?> list = new ArrayList<?>(); // 编译报错 |
12 |
| - Map<String, ? extends Number> map = new HashMap<String, ? extends Number>(); // 编译报错 |
13 |
| - ``` |
| 10 | +```java |
| 11 | +List<?> list = new ArrayList<?>(); // 编译报错 |
| 12 | +Map<String, ? extends Number> map = new HashMap<String, ? extends Number>(); // 编译报错 |
| 13 | +``` |
14 | 14 |
|
15 | 15 | 这通常不困难。 获取和放置告诉我们,如果一个结构体包含通配符,那么我们只应该从中得到值(如果它是一个扩展通配符)或者只将值放入它中(如果它是一个超级
|
16 | 16 | 通配符)。 为了使结构有用,我们必须同时做到这两点。 因此,我们通常以精确的类型创建结构,即使我们使用通配符类型将值放入或从结构中获取值,如下例所示:
|
17 | 17 |
|
18 | 18 | ```java
|
19 |
| - List<Number> nums = new ArrayList<Number>(); |
20 |
| - List<? super Number> sink = nums; |
21 |
| - List<? extends Number> source = nums; |
22 |
| - for (int i=0; i<10; i++) sink.add(i); |
23 |
| - double sum=0; for (Number num : source) sum+=num.doubleValue(); |
| 19 | +List<Number> nums = new ArrayList<Number>(); |
| 20 | +List<? super Number> sink = nums; |
| 21 | +List<? extends Number> source = nums; |
| 22 | +for (int i=0; i<10; i++) sink.add(i); |
| 23 | +double sum=0; for (Number num : source) sum+=num.doubleValue(); |
24 | 24 | ```
|
25 | 25 |
|
26 | 26 | 这里通配符出现在第二行和第三行,但不在创建列表的第一行。
|
27 | 27 |
|
28 | 28 | 禁止包含通配符的实例创建中只有顶级参数。 允许嵌套通配符。 因此,以下是合法的:
|
29 | 29 |
|
30 | 30 | ```java
|
31 |
| - List<List<?>> lists = new ArrayList<List<?>>(); |
32 |
| - lists.add(Arrays.asList(1,2,3)); |
33 |
| - lists.add(Arrays.asList("four","five")); |
34 |
| - assert lists.toString().equals("[[1, 2, 3], [four, five]]"); |
| 31 | +List<List<?>> lists = new ArrayList<List<?>>(); |
| 32 | +lists.add(Arrays.asList(1,2,3)); |
| 33 | +lists.add(Arrays.asList("four","five")); |
| 34 | +assert lists.toString().equals("[[1, 2, 3], [four, five]]"); |
35 | 35 | ```
|
36 | 36 |
|
37 | 37 | 即使列表的列表是以通配符类型创建的,其中的每个单独列表都有一个特定的类型:第一个列表是整数列表,第二个列表是字符串列表。 通配符类型禁止我们将内部列表
|
|
41 | 41 | 陈述:
|
42 | 42 |
|
43 | 43 | ```java
|
44 |
| - List<?> list = new ArrayList<Object>(); // ok |
45 |
| - List<?> list = new List<Object>() // 编译报错 |
46 |
| - List<?> list = new ArrayList<?>() // 编译报错 |
| 44 | +List<?> list = new ArrayList<Object>(); // ok |
| 45 | +List<?> list = new List<Object>() // 编译报错 |
| 46 | +List<?> list = new ArrayList<?>() // 编译报错 |
47 | 47 | ```
|
48 | 48 |
|
49 | 49 | 第一个是合法的; 第二个是非法的,因为实例创建表达式需要一个类,而不是一个接口; 第三个是非法的,因为实例创建表达式需要普通类型而不是通配符。
|
|
54 | 54 | **泛型方法调用**如果泛型方法调用包含显式类型参数,那么这些类型参数不能是通配符。 例如,假设我们有以下通用方法:
|
55 | 55 |
|
56 | 56 | ```java
|
57 |
| - class Lists { |
58 |
| - public static <T> List<T> factory() { return new ArrayList<T>(); } |
59 |
| - } |
| 57 | +class Lists { |
| 58 | + public static <T> List<T> factory() { return new ArrayList<T>(); } |
| 59 | +} |
60 | 60 | ```
|
61 | 61 |
|
62 | 62 | 您可以选择推断的类型参数,也可以传递一个明确的类型参数。 以下两项都是合法的:
|
63 | 63 |
|
64 | 64 | ```java
|
65 |
| - List<?> list = Lists.factory(); |
66 |
| - List<?> list = Lists.<Object>factory(); |
| 65 | +List<?> list = Lists.factory(); |
| 66 | +List<?> list = Lists.<Object>factory(); |
67 | 67 | ```
|
68 | 68 |
|
69 | 69 | 如果传递一个显式的类型参数,它不能是通配符:
|
70 | 70 |
|
71 | 71 | ```java
|
72 |
| - List<?> list = Lists.<?>factory(); // 编译报错 |
| 72 | +List<?> list = Lists.<?>factory(); // 编译报错 |
73 | 73 | ```
|
74 | 74 |
|
75 | 75 | 和以前一样,可以使用嵌套通配符:
|
76 | 76 |
|
77 | 77 | ```java
|
78 |
| - List<List<?>> = Lists.<List<?>>factory(); // ok |
| 78 | +List<List<?>> = Lists.<List<?>>factory(); // ok |
79 | 79 | ```
|
80 | 80 |
|
81 | 81 | 这种限制的动机与之前的相似。 再次,目前还不清楚是否有必要,但这不太可能成为问题。
|
|
84 | 84 | 型参数,则这些类型不能是通配符。例如,这个声明是非法的:
|
85 | 85 |
|
86 | 86 | ```java
|
87 |
| - class AnyList extends ArrayList<?> {...} // 编译报错 |
| 87 | +class AnyList extends ArrayList<?> {...} // 编译报错 |
88 | 88 | ```
|
89 | 89 |
|
90 | 90 | 这也是:
|
91 | 91 |
|
92 | 92 | ```java
|
93 |
| - class AnotherList implements List<?> {...} // 编译报错 |
| 93 | +class AnotherList implements List<?> {...} // 编译报错 |
94 | 94 | ```
|
95 | 95 |
|
96 | 96 | 但是,像以前一样,嵌套通配符是允许的:
|
97 | 97 |
|
98 | 98 | ```java
|
99 |
| - class NestedList extends ArrayList<List<?>> {...} // ok |
| 99 | +class NestedList extends ArrayList<List<?>> {...} // ok |
100 | 100 | ```
|
101 | 101 |
|
102 | 102 | 这种限制的动机与前两种类似。 与以前一样,目前还不清楚是否有必要,但不太可能成为问题。
|
|
0 commit comments