|
3 | 3 |
|
4 | 4 | ### 通配符和继承
|
5 | 5 |
|
6 |
| -- `Collection`接口中的另一个方法是`addAll`,它将一个集合的所有成员添加到另一个集合中: |
| 6 | +`Collection` 接口中的另一个方法是 `addAll`,它将一个集合的所有成员添加到另一个集合中: |
7 | 7 |
|
8 | 8 | ```java
|
9 | 9 | interface Collection<E> {
|
|
12 | 12 | ...
|
13 | 13 | }
|
14 | 14 | ```
|
15 |
| -- 显然,给定`E`类型的元素的集合,可以将另一个集合的所有成员添加到`E`类型的元素中。 |
16 |
| -这个古怪的短语`? extends E`意味着也可以添加元素任何类型都是`E`的子类型的所有成员 。 |
17 |
| -问号称为通配符,因为它代表某种类型,它是`E`的子类型。 |
18 | 15 |
|
19 |
| -- 这是一个例子。 我们创建一个空的数字列表,并首先添加一个整数列表, |
20 |
| -然后是一个双精度列表: |
| 16 | +显然,给定 `E` 类型的元素的集合,可以将另一个集合的所有成员添加到 `E` 类型的元素中。这个古怪的短语 `? extends E` 意味着也可以添加元素任何类型都是 |
| 17 | +`E` 的子类型的所有成员 。问号称为通配符,因为它代表某种类型,它是 `E` 的子类型。 |
| 18 | + |
| 19 | +这是一个例子。 我们创建一个空的数字列表,并首先添加一个整数列表,然后是一个双精度列表: |
21 | 20 |
|
22 | 21 | ```java
|
23 | 22 | List<Number> nums = new ArrayList<Number>();
|
|
28 | 27 | assert nums.toString().equals("[1, 2, 2.78, 3.14]");
|
29 | 28 | ```
|
30 | 29 |
|
31 |
| -- 第一个调用是允许的,因为`nums`的类型是`List<Number>`,它是`Collection<Number>`的子类型, |
32 |
| -而`ints`的类型是`List<Integer>`,它是`Collection`的子类型`Collection<? extends Number>`。 |
33 |
| -第二个调用同样被允许。 在这两个调用中,`E`被认为是`Number`。 如果`addAll`的方法签名没有使用通配符, |
34 |
| -那么将不允许添加整数列表和双精度列表的调用; 你只能添加一个明确声明为数字列表的列表。 |
| 30 | +第一个调用是允许的,因为 `nums` 的类型是 `List<Number>`,它是 `Collection<Number>` 的子类型,而 `ints` 的类型是 `List<Integer>` ,它是 |
| 31 | +`Collection` 的子类型 `Collection<? extends Number>`。 第二个调用同样被允许。 在这两个调用中,`E` 被认为是 `Number`。 如果 `addAll` 的方法签名 |
| 32 | +没有使用通配符,那么将不允许添加整数列表和双精度列表的调用; 你只能添加一个明确声明为数字列表的列表。 |
35 | 33 |
|
36 |
| -- 声明变量时我们也可以使用通配符。 下面是上一节末尾的示例变体,通过在第二行添加通配符进行更改: |
| 34 | +声明变量时我们也可以使用通配符。 下面是上一节末尾的示例变体,通过在第二行添加通配符进行更改: |
37 | 35 |
|
38 | 36 | ```java
|
39 | 37 | List<Integer> ints = new ArrayList<Integer>();
|
|
43 | 41 | nums.add(3.14); // 编译报错
|
44 | 42 | assert ints.toString().equals("[1, 2, 3.14]"); // uh oh!
|
45 | 43 | ```
|
46 |
| -- 之前,第四行导致了一个编译时错误(因为`List<Integer>`不是`List<Number>`的子类型), |
47 |
| -但是第五行没有问题(因为`double`是一个数字,所以你可以添加一个`double`到一个`List<Number>`)。 |
48 |
| -现在,第四行是正确的(因为`List<Integer>`是`List<? extends Number>`的子类型), |
49 |
| -但是第五行会导致编译时错误(因为您不能将一个`double`添加到`List<? extends Number>` , |
50 |
| -因为它可能是一些其他的数字子类型的列表)。 和以前一样,最后一行显示为什么之前的行是非法的! |
51 | 44 |
|
52 |
| -- 一般来说,如果一个结构包含一个表单类型的元素? 扩展`E`,我们可以从结构中获得元素, |
53 |
| -但是我们不能将元素放入结构中。 为了将元素放入结构中,我们需要使用另一种通配符, |
54 |
| -如下一节所述。 |
| 45 | +之前,第四行导致了一个编译时错误(因为 `List<Integer>` 不是 `List<Number>` 的子类型),但是第五行没有问题(因为 `double` 是一个数字,所以你可以添 |
| 46 | +加一个 `double` 到一个 `List<Number>`)。 现在,第四行是正确的(因为 `List<Integer>` 是 `List<? extends Number>` 的子类型),但是第五行会导致编 |
| 47 | +译时错误(因为您不能将一个 `double` 添加到 `List<? extends Number>` ,因为它可能是一些其他的数字子类型的列表)。 和以前一样,最后一行显示为什么之 |
| 48 | +前的行是非法的! |
| 49 | + |
| 50 | +一般来说,如果一个结构包含一个表单类型的元素 `? extends E`,我们可以从结构中获得元素,但是我们不能将元素放入结构中。 为了将元素放入结构中,我们需要 |
| 51 | +使用另一种通配符,如下一节所述。 |
55 | 52 |
|
56 | 53 |
|
57 | 54 | 《《《 [下一节](03_Wildcards_with_super.md) <br/>
|
58 |
| -《《《 [返回首页](../README.md) |
| 55 | +《《《 [返回首页](../README.md) |
0 commit comments