Skip to content

Commit a9f4b2c

Browse files
authored
Update 07_Wildcard_Capture.md
1 parent daaa6fc commit a9f4b2c

File tree

1 file changed

+38
-38
lines changed

1 file changed

+38
-38
lines changed

ch02/07_Wildcard_Capture.md

+38-38
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,63 @@
33

44
### 通配符捕获
55

6-
当调用泛型方法时,可以选择类型参数以匹配由通配符表示的未知类型。 这被称为通配符捕获。
6+
当调用泛型方法时,可以选择类型参数以匹配由通配符表示的未知类型。这被称为通配符捕获。
77

8-
考虑工具类 `java.util.Collections` 中的反向方法,它接受任何类型的列表并将其反转。 它可以是以下两个签名中的任何一个,它们是相同的:
8+
考虑工具类 `java.util.Collections` 中的反向方法,它接受任何类型的列表并将其反向。它可以是以下两个签名中的任何一个,它们是相同的:
99

10-
```java
11-
public static void reverse(List<?> list);
12-
public static void <T> reverse(List<T> list);
13-
```
10+
```java
11+
public static void reverse(List<?> list);
12+
public static void <T> reverse(List<T> list);
13+
```
1414

1515
通配符签名稍短且更清晰,是类库中使用的签名。如果使用第二个签名,则很容易实现该方法:
1616

17-
```java
18-
public static void <T> reverse(List<T> list) {
19-
List<T> tmp = new ArrayList<T>(list);
20-
for (int i = 0; i < list.size(); i++) {
21-
list.set(i, tmp.get(list.size()-i-1));
22-
}
17+
```java
18+
public static void <T> reverse(List<T> list) {
19+
List<T> tmp = new ArrayList<T>(list);
20+
for (int i = 0; i < list.size(); i++) {
21+
list.set(i, tmp.get(list.size()-i-1));
2322
}
24-
```
23+
}
24+
```
2525

2626
这会将参数复制到临时列表中,然后以相反的顺序将副本写回到原始文件中。如果您尝试使用类似方法体的第一个签名,它将不起作用:
27-
28-
```java
29-
public static void reverse(List<?> list) {
30-
List<Object> tmp = new ArrayList<Object>(list);
31-
for (int i = 0; i < list.size(); i++) {
32-
list.set(i, tmp.get(list.size()-i-1)); // 编译报错
33-
}
27+
28+
```java
29+
public static void reverse(List<?> list) {
30+
List<Object> tmp = new ArrayList<Object>(list);
31+
for (int i = 0; i < list.size(); i++) {
32+
list.set(i, tmp.get(list.size()-i-1)); // 编译报错
3433
}
35-
```
34+
}
35+
```
3636

3737
现在从拷贝写入原始文件是不合法的,因为我们试图从对象列表写入未知类型的列表。 用 `List<?>` 替换 `List<Object>` 不会解决问题,因为现在我们有两个带有
3838
(可能不同)未知元素类型的列表。
3939

4040
相反,您可以通过使用第二个签名实现私有方法并从第一个签名调用第二个签名来实现具有第一个签名的方法:
4141

42-
```java
43-
public static void reverse(List<?> list) { rev(list); }
44-
private static <T> void rev(List<T> list) {
45-
List<T> tmp = new ArrayList<T>(list);
46-
for (int i = 0; i < list.size(); i++) {
47-
list.set(i, tmp.get(list.size()-i-1));
48-
}
42+
```java
43+
public static void reverse(List<?> list) { rev(list); }
44+
private static <T> void rev(List<T> list) {
45+
List<T> tmp = new ArrayList<T>(list);
46+
for (int i = 0; i < list.size(); i++) {
47+
list.set(i, tmp.get(list.size()-i-1));
4948
}
50-
```
49+
}
50+
```
5151

52-
在这里我们说类型变量T已经捕获了通配符。 这是处理通配符时通常有用的技巧,值得了解。
52+
在这里我们说类型变量 `T` 已经捕获了通配符。 这是处理通配符时通常有用的技巧,值得了解。
5353

54-
了解通配符捕获的另一个原因是,即使您不使用上述技术,它也可以显示在错误消息中。 通常,每次出现通配符都表示某种未知类型。 如果编译器打印包含此类型的错
55-
误消息,则称为捕获?。 例如,使用 `Sun` 当前的编译器,反向版本不正确会生成以下错误消息:
54+
了解通配符捕获的另一个原因是,即使您不使用上述技术,它也可以显示在错误消息中。通常,每次出现通配符都表示某种未知类型。 如果编译器打印包含此类型的错误
55+
消息,则称为捕获?。 例如,使用 `Sun` 当前的编译器,反向版本不正确会生成以下错误消息:
5656

57-
```java
58-
Capture.java:6: set(int,capture of ?) in java.util.List<capture of ?>
59-
cannot be applied to (int,java.lang.Object)
60-
list.set(i, tmp.get(list.size()-i-1));
61-
^
62-
```
57+
```java
58+
Capture.java:6: set(int,capture of ?) in java.util.List<capture of ?>
59+
cannot be applied to (int,java.lang.Object)
60+
list.set(i, tmp.get(list.size()-i-1));
61+
^
62+
```
6363

6464
因此,如果你看到这个奇怪的短语 ` capture of ?` 在错误消息中,它将来自通配符类型。 即使有两个不同的通配符,编译器也会打印与每个相关的类型作为
6565
`capture of ?`。 有界的通配符会生成更加冗长的名称,如 `capture of ? extends Number`

0 commit comments

Comments
 (0)