|
3 | 3 |
|
4 | 4 | ### 泛型方法和可变参数
|
5 | 5 |
|
6 |
| -- 这是接受任何类型的数组并将其转换为列表的方法: |
| 6 | +这是接受任何类型的数组并将其转换为列表的方法: |
7 | 7 |
|
8 |
| - ```java |
9 |
| - class Lists { |
10 |
| - public static <T> List<T> toList(T[] arr) { |
| 8 | +```java |
| 9 | + class Lists { |
| 10 | + public static <T> List<T> toList(T[] arr) { |
11 | 11 | List<T> list = new ArrayList<T>();
|
12 | 12 | for (T elt : arr) list.add(elt);
|
13 | 13 | return list;
|
14 | 14 | }
|
15 | 15 | }
|
16 |
| - ``` |
17 |
| -- 静态方法`toList`接受一个`T[]`类型的数组并返回一个类型列表`List<T>`,并且对于任何类型T都这样做。 |
18 |
| -这通过在开头写入`<T>`来指示方法签名,它将`T`声明为一个新的类型变量。 一种方法用这种方式声明一个类型变量被称为泛型方法。 |
19 |
| -类型的范围变量`T`对于方法本身是本地的; 它可能出现在方法签名和方法体,但不在方法之外。 |
| 16 | +``` |
| 17 | + |
| 18 | +静态方法 `toList` 接受一个 `T[]` 类型的数组并返回一个类型列表 `List<T>`,并且对于任何类型 `T` 都这样做。这通过在开头写入`<T>`来指示方法签名,它将 |
| 19 | +`T` 声明为一个新的类型变量。 一种方法用这种方式声明一个类型变量被称为泛型方法。 类型的范围变量 `T` 对于方法本身是本地的; 它可能出现在方法签名和方法 |
| 20 | +体,但不在方法之外。 |
20 | 21 |
|
21 |
| -- 该方法可以如下调用: |
22 |
| - |
23 |
| - ```java |
24 |
| - List<Integer> ints = Lists.toList(new Integer[] { 1, 2, 3 }); |
25 |
| - List<String> words = Lists.toList(new String[] { "hello", "world" }); |
26 |
| - ``` |
27 |
| - 在第一行中,装箱将`int`,`1,2,3`转换为`Integer`。 |
| 22 | +该方法可以如下调用: |
28 | 23 |
|
29 |
| -- 将参数打包到一个数组中是非常麻烦的。 对于方法的最后一个参数是数组的情况,可变参数特性允许使用一种特别的, |
30 |
| -更方便的语法。 要使用这个特性,我们在方法声明中用`T...`替换`T[]`: |
| 24 | +```java |
| 25 | + List<Integer> ints = Lists.toList(new Integer[] { 1, 2, 3 }); |
| 26 | + List<String> words = Lists.toList(new String[] { "hello", "world" }); |
| 27 | +``` |
| 28 | + |
| 29 | +在第一行中,装箱将 `int`,`1`,`2`,`3` 转换为 `Integer`。 |
31 | 30 |
|
32 |
| - ```java |
33 |
| - class Lists { |
34 |
| - public static <T> List<T> toList(T... arr) { |
35 |
| - List<T> list = new ArrayList<T>(); |
36 |
| - for (T elt : arr) list.add(elt); |
37 |
| - return list; |
38 |
| - } |
| 31 | +将参数打包到一个数组中是非常麻烦的。 对于方法的最后一个参数是数组的情况,可变参数特性允许使用一种特别的、更方便的语法。 要使用这个特性,我们在方法声 |
| 32 | +明中用 `T...` 替换 `T[]`: |
| 33 | + |
| 34 | +```java |
| 35 | + class Lists { |
| 36 | + public static <T> List<T> toList(T... arr) { |
| 37 | + List<T> list = new ArrayList<T>(); |
| 38 | + for (T elt : arr) list.add(elt); |
| 39 | + return list; |
39 | 40 | }
|
40 |
| - ``` |
41 |
| - 现在该方法可以被调用,如下所示: |
42 |
| - ```java |
43 |
| - List<Integer> ints = Lists.toList(1, 2, 3); |
44 |
| - List<String> words = Lists.toList("hello", "world"); |
45 |
| - ``` |
46 |
| - 这只是我们上面写的内容的简写。 在运行时,参数就像以前一样被打包到传递给方法的数组中。 |
| 41 | + } |
| 42 | +``` |
| 43 | + |
| 44 | +现在该方法可以被调用,如下所示: |
| 45 | + |
| 46 | +```java |
| 47 | + List<Integer> ints = Lists.toList(1, 2, 3); |
| 48 | + List<String> words = Lists.toList("hello", "world"); |
| 49 | +``` |
| 50 | + |
| 51 | +这只是我们上面写的内容的简写。 在运行时,参数就像以前一样被打包到传递给方法的数组中。 |
47 | 52 |
|
48 |
| -- 任何数量的参数都可以在最后的可变参数之前。 这是一个方法,接受一个列表,并将所有附加参数添加到列表的末尾: |
| 53 | +任何数量的参数都可以在最后的可变参数之前。 这是一个方法,接受一个列表,并将所有附加参数添加到列表的末尾: |
49 | 54 |
|
50 |
| - ```java |
51 |
| - public static <T> void addAll(List<T> list, T... arr) { |
52 |
| - for (T elt : arr) list.add(elt); |
53 |
| - } |
54 |
| - ``` |
| 55 | +```java |
| 56 | + public static <T> void addAll(List<T> list, T... arr) { |
| 57 | + for (T elt : arr) list.add(elt); |
| 58 | + } |
| 59 | +``` |
55 | 60 |
|
56 |
| -- 每当声明可变参数时,可以将参数列表传递给数组,或直接显式传递数组。 因此,可以如下调用前面的方法: |
| 61 | +每当声明可变参数时,可以将参数列表传递给数组,或直接显式传递数组。 因此,可以如下调用前面的方法: |
57 | 62 |
|
58 |
| - ```java |
59 |
| - List<Integer> ints = new ArrayList<Integer>(); |
60 |
| - Lists.addAll(ints, 1, 2); |
61 |
| - Lists.addAll(ints, new Integer[] { 3, 4 }); |
62 |
| - assert ints.toString().equals("[1, 2, 3, 4]"); |
63 |
| - ``` |
| 63 | +```java |
| 64 | + List<Integer> ints = new ArrayList<Integer>(); |
| 65 | + Lists.addAll(ints, 1, 2); |
| 66 | + Lists.addAll(ints, new Integer[] { 3, 4 }); |
| 67 | + assert ints.toString().equals("[1, 2, 3, 4]"); |
| 68 | +``` |
64 | 69 |
|
65 |
| -- 我们稍后会看到,当我们尝试创建一个包含泛型类型的数组时,我们总是会收到一个未经检查的警告。 |
66 |
| -由于可变参数总是创建一个数组,所以只有在参数没有泛型时才能使用它们(见6.8节)。 |
| 70 | +我们稍后会看到,当我们尝试创建一个包含泛型类型的数组时,我们总是会收到一个未经检查的警告。 由于可变参数总是创建一个数组,所以只有在参数没有泛型时才能 |
| 71 | +使用它们(见6.8节)。 |
67 | 72 |
|
68 |
| -- 在前面的例子中,泛型方法的类型参数被推断出来,但是也可以被明确给出,如下面的例子所示: |
| 73 | +在前面的例子中,泛型方法的类型参数被推断出来,但是也可以被明确给出,如下面的例子所示: |
69 | 74 |
|
70 |
| - ```java |
71 |
| - List<Integer> ints = Lists.<Integer>toList(); |
72 |
| - List<Object> objs = Lists.<Object>toList(1, "two"); |
73 |
| - ``` |
| 75 | +```java |
| 76 | + List<Integer> ints = Lists.<Integer>toList(); |
| 77 | + List<Object> objs = Lists.<Object>toList(1, "two"); |
| 78 | +``` |
74 | 79 |
|
75 |
| -- 显式参数通常不是必需的,但是在这里给出的例子中它们是有帮助的。 在第一个例子中, |
76 |
| -如果没有类型参数,那么`Sun`的编译器用来推断正确类型的类型推断算法的信息就太少了。 |
77 |
| -它推断`toList`的参数是一个任意泛型类型的空数组,而不是一个空整型数组, |
78 |
| -这触发了前面描述的未经检查的警告。 (`Eclipse`编译器使用不同的推理算法, |
79 |
| -并在没有显式参数的情况下正确地编译相同的行。)在第二个示例中,没有类型参数, |
80 |
| -类型推理算法的信息太多,无法推断出正确的类型。 你可能会认为`Object`是唯一一个整数和字符串有共同的类型, |
81 |
| -但实际上它们都实现了`Serializable`和`Comparable`接口。 类型推断算法不能选择这三种中的哪一种是正确的类型。 |
| 80 | +显式参数通常不是必需的,但是在这里给出的例子中它们是有帮助的。 在第一个例子中,如果没有类型参数,那么 `Sun` 的编译器用来推断正确类型的类型推断算法的 |
| 81 | +信息就太少了。 它推断 `toList` 的参数是一个任意泛型类型的空数组,而不是一个空整型数组,这触发了前面描述的未经检查的警告。 (`Eclipse` 编译器使用不 |
| 82 | +同的推理算法,并在没有显式参数的情况下正确地编译相同的行。)在第二个示例中,没有类型参数,类型推理算法的信息太多,无法推断出正确的类型。 你可能会认为 |
| 83 | +`Object` 是唯一一个整数和字符串有共同的类型,但实际上它们都实现了 `Serializable` 和 `Comparable` 接口。 类型推断算法不能选择这三种中的哪一种是正确 |
| 84 | +的类型。 |
82 | 85 |
|
83 |
| -- 一般来说,下面的经验法则就足够了:在对通用方法的调用中,如果存在的话是一个或多个参数对应于一个类型参数, |
84 |
| -他们都有相同的类型,那么可以推断出类型参数; 如果没有对应于类型参数的参数, |
85 |
| -或者参数属于预期类型的不同子类型,则必须明确给出类型参数。 |
| 86 | +一般来说,下面的经验法则就足够了:在对通用方法的调用中,如果存在的话是一个或多个参数对应于一个类型参数,他们都有相同的类型,那么可以推断出类型参数; |
| 87 | +如果没有对应于类型参数的参数,或者参数属于预期类型的不同子类型,则必须明确给出类型参数。 |
86 | 88 |
|
87 |
| -- 当一个类型参数传递给泛型方法调用时,它将以角度出现括号在左边,就像在方法声明中一样。 |
88 |
| -`Java`语法要求类型参数只能出现在使用虚线形式的方法调用中。 即使方法`toList`在调用代码的同一个类中定义, |
89 |
| -我们也不能缩短它如下: |
| 89 | +当一个类型参数传递给泛型方法调用时,它将以角度出现括号在左边,就像在方法声明中一样。`Java` 语法要求类型参数只能出现在使用虚线形式的方法调用中。 即使 |
| 90 | +方法 `toList` 在调用代码的同一个类中定义,我们也不能缩短它如下: |
90 | 91 |
|
91 |
| - ```java |
92 |
| - List<Integer> ints = <Integer>toList(); // 编译报错 |
93 |
| - ``` |
94 |
| - 这是非法的,因为它会混淆解析器。 |
| 92 | +```java |
| 93 | + List<Integer> ints = <Integer>toList(); // 编译报错 |
| 94 | +``` |
| 95 | + |
| 96 | +这是非法的,因为它会混淆解析器。 |
95 | 97 |
|
96 |
| -- 方法集合框架中的`Arrays.asList`和`Collections.addAll`是类似于之前显示的`toList`和`addAll`。 |
97 |
| -(这两个类都在`java.util`包中)`asList`的集合框架版本不返回`ArrayList`,而是返回由给定数组支持的专用列表类。 |
98 |
| -此外,其版本的`addAll`作用于一般集合,而不仅仅是列表。 |
| 98 | +方法集合框架中的 `Arrays.asList` 和 `Collections.addAll` 是类似于之前显示的 `toList` 和 `addAll`。 (这两个类都在 `java.util` 包中)`asList` |
| 99 | +的集合框架版本不返回 `ArrayList`,而是返回由给定数组支持的专用列表类。 此外,其版本的 `addAll` 作用于一般集合,而不仅仅是列表。 |
99 | 100 |
|
100 | 101 | 《《《 [下一节](05_Assertions.md) <br/>
|
101 |
| -《《《 [返回首页](../README.md) |
| 102 | +《《《 [返回首页](../README.md) |
0 commit comments