|
1 | 1 | ## 具有传统客户端的通用库
|
2 | 2 |
|
3 |
| -现在让我们考虑一下这种情况,即在客户端保留其旧版本时,库更新为泛型。这可能是因为没有足够的时间一次转换所有内容,或者因为类库和客户由不同的组织控制。这对应于向后兼容性的最重要情况,其中 `Java 5` 的通用集合框架必须仍然可以与针对 `Java 1.4` 中的集合框架编写的传统客户端一起工作。 |
| 3 | +现在让我们考虑一下这种情况,即在客户端保留其旧版本时,库更新为泛型。这可能是因为没有足够的时间一次转换所有内容,或者因为类库和客户由不同的组织控制。 |
| 4 | +这对应于向后兼容性的最重要情况,其中 `Java 5` 的通用集合框架必须仍然可以与针对 `Java 1.4` 中的集合框架编写的传统客户端一起工作。 |
4 | 5 |
|
5 |
| -为了支持进化,每当定义参数化类型时,`Java` 也会识别相应的非参数化类型的类型,称为原始类型。例如,参数化类型 `Stack<E>` 对应于原始类型 `Stack`,参数化类型 `ArrayStack<E>` 对应于原始类型 `ArrayStack`。 |
| 6 | +为了支持进化,每当定义参数化类型时,`Java` 也会识别相应的非参数化类型的类型,称为原始类型。例如,参数化类型 `Stack<E>` 对应于原始类型 `Stack`,参数 |
| 7 | +化类型 `ArrayStack<E>` 对应于原始类型 `ArrayStack`。 |
6 | 8 |
|
7 |
| -每个参数化类型都是相应原始类型的子类型,因此可以在需要原始类型的位置传递参数化类型的值。通常,传递一个超类型值是一个错误,其中它的子类型的值是预期的,但是 `Java` 确实允许在需要参数化类型的地方传递一个原始类型的值 - 然而,它通过生成标志来标记这种情况未经检查的转换警告。例如,您可以将 `Stack<E>` 类型的值分配给 `Stack` 类型的变量,因为前者是后者的子类型。您也可以将 `Stack` 类型的值分配给 `Stack<E>` 类型的变量,但这会生成未经检查的转换警告。 |
| 9 | +每个参数化类型都是相应原始类型的子类型,因此可以在需要原始类型的位置传递参数化类型的值。通常,传递一个超类型值是一个错误,其中它的子类型的值是预期 |
| 10 | +的,但是 `Java` 确实允许在需要参数化类型的地方传递一个原始类型的值 - 然而,它通过生成标志来标记这种情况未经检查的转换警告。例如,您可以将 |
| 11 | +`Stack<E>` 类型的值分配给 `Stack` 类型的变量,因为前者是后者的子类型。您也可以将 `Stack` 类型的值分配给 `Stack<E>` 类型的变量,但这会生成未经检查 |
| 12 | +的转换警告。 |
8 | 13 |
|
9 |
| -具体来说,考虑从例 `5-2` 的 `Stack<E>`,`ArrayStack<E>` 和 `Stacks` 的通用源(例如,在目录 `g` 中)使用来自例 `5-1` 的 `Client` 的遗留源(例如,在目录 `l`)。 `Sun` 的 `Java 5` 编译器会产生以下消息: |
| 14 | +具体来说,考虑从例 `5-2` 的 `Stack<E>`,`ArrayStack<E>` 和 `Stacks` 的通用源(例如,在目录 `g` 中)使用来自例 `5-1` 的 `Client` 的遗留源(例 |
| 15 | +如,在目录 `l`)。 `Sun` 的 `Java 5` 编译器会产生以下消息: |
10 | 16 |
|
11 | 17 | ```java
|
12 | 18 | % javac g/Stack.java g/ArrayStack.java g/Stacks.java l/Client.java
|
13 | 19 | Note: Client.java uses unchecked or unsafe operations.
|
14 | 20 | Note: Recompile with -Xlint:unchecked for details.
|
15 | 21 | ```
|
16 | 22 |
|
17 |
| -未经检查的警告表明,编译器无法提供与泛型在统一使用时相同的安全保证。 但是,当通过更新遗留代码生成通用代码时,我们知道从两者都生成了等效的类文件,因此(即使未经检查的警告)使用通用库运行旧版客户端将产生与运行旧版客户端相同的结果 与遗留图书馆。 在这里,我们假设更新图书馆的唯一改变是引入泛型,并且不管是故意还是错误地引入行为改变。 |
| 23 | +未经检查的警告表明,编译器无法提供与泛型在统一使用时相同的安全保证。 但是,当通过更新遗留代码生成通用代码时,我们知道从两者都生成了等效的类文件,因此 |
| 24 | +(即使未经检查的警告)使用通用库运行旧版客户端将产生与运行旧版客户端相同的结果 与遗留图书馆。 在这里,我们假设更新图书馆的唯一改变是引入泛型,并且不 |
| 25 | +管是故意还是错误地引入行为改变。 |
18 | 26 |
|
19 | 27 | 例 `5-2`。 具有通用客户端的通用库
|
20 | 28 |
|
|
88 | 96 | 3 warnings
|
89 | 97 | ```
|
90 | 98 |
|
91 |
| -并非每种原始类型都会引发警告。因为每个参数化类型都是相应原始类型的子类型,但是相反,传递一个参数化类型(其中原始类型是预期的)是安全的(因此,没有警告来获得反向结果),但是将原始类型传递给参数化预期类型会发出警告(因此,传递参数时会发出警告);这是替代原则的一个例子。当我们在原始类型的接收者上调用方法时,该方法被视为类型参数是通配符,因此从原始类型获取值是安全的(因此,不会弹出调用 `pop` 的警告),而是将原始类型的值会发出警告(因此,调用 `push` 的警告);这是获取和放置原则的一个实例。 |
| 99 | +并非每种原始类型都会引发警告。因为每个参数化类型都是相应原始类型的子类型,但是相反,传递一个参数化类型(其中原始类型是预期的)是安全的(因此,没有警 |
| 100 | +告来获得反向结果),但是将原始类型传递给参数化预期类型会发出警告(因此,传递参数时会发出警告);这是替代原则的一个例子。当我们在原始类型的接收者上调用 |
| 101 | +方法时,该方法被视为类型参数是通配符,因此从原始类型获取值是安全的(因此,不会弹出调用 `pop` 的警告),而是将原始类型的值会发出警告(因此,调用 |
| 102 | +`push` 的警告);这是获取和放置原则的一个实例。 |
92 | 103 |
|
93 |
| -即使您没有编写任何通用代码,您仍可能会遇到进化问题,因为其他人已经使其代码生成了基因。这会影响使用已由 `Sun` 进行基因化的集合框架的遗留代码的所有人。因此,在旧版客户端中使用泛型库最重要的情况是使用 `Java 5` 集合框架和为 `Java 1.4` 集合框架编写的遗留代码。 |
| 104 | +即使您没有编写任何通用代码,您仍可能会遇到进化问题,因为其他人已经使其代码生成了基因。这会影响使用已由 `Sun` 进行基因化的集合框架的遗留代码的所有人。 |
| 105 | +因此,在旧版客户端中使用泛型库最重要的情况是使用 `Java 5` 集合框架和为 `Java 1.4` 集合框架编写的遗留代码。 |
94 | 106 |
|
95 |
| -特别是,在示例 `5-1` 中将 `Java 5` 编译器应用于遗留代码时,也会发出未经检查的警告,因为传统类 `ArrayStack` 中使用了基本化的类 `ArrayList`。下面是当我们用 `Java 5` 编译器和库编译所有文件的旧版本时发生的情况: |
| 107 | +特别是,在示例 `5-1` 中将 `Java 5` 编译器应用于遗留代码时,也会发出未经检查的警告,因为传统类 `ArrayStack` 中使用了基本化的类 `ArrayList`。下面是 |
| 108 | +当我们用 `Java 5` 编译器和库编译所有文件的旧版本时发生的情况: |
96 | 109 |
|
97 | 110 | ```java
|
98 | 111 | % javac -Xlint:unchecked l/Stack.java l/ArrayStack.java \
|
|
106 | 119 |
|
107 | 120 | 在这里,传统方法 `push` 中使用泛型方法 `add` 的警告是由于类似于从旧客户端发出使用泛型方法 `push` 的先前警告的原因而发布的。
|
108 | 121 |
|
109 |
| -将编译器配置为反复发出您打算忽略的警告是一种很不好的做法。 这会让人分心,更糟的是,它可能会导致你忽视需要注意的警告 - 就像在狼的小男孩的寓言中一样。 在纯代码的情况下,可以使用 `-source 1.4` 开关关闭此类警告: |
| 122 | +将编译器配置为反复发出您打算忽略的警告是一种很不好的做法。 这会让人分心,更糟的是,它可能会导致你忽视需要注意的警告 - 就像在狼的小男孩的寓言中一样。 |
| 123 | +在纯代码的情况下,可以使用 `-source 1.4` 开关关闭此类警告: |
110 | 124 |
|
111 | 125 | ```java
|
112 | 126 | % javac -source 1.4 l/Stack.java l/ArrayStack.java \
|
113 | 127 | % l/Stacks.java l/Client.java
|
114 | 128 | ```
|
115 | 129 |
|
116 |
| -这编译了遗留代码并且没有发出警告或错误。 这种关闭警告的方法只适用于真正的遗留代码,没有 `Java 5` 中引入的通用功能或其他功能。 也可以使用注释关闭未经检查的警告,如下一节所述,即使使用 `Java 5` 中引入的功能,也可以使用这些警告。 |
117 |
| - |
118 |
| - |
119 |
| - |
120 |
| - |
121 |
| - |
122 |
| - |
123 |
| - |
124 |
| - |
125 |
| - |
126 |
| - |
127 |
| - |
128 |
| - |
129 |
| - |
130 |
| - |
131 |
| - |
132 |
| - |
133 |
| - |
134 |
| - |
135 |
| - |
136 |
| - |
137 |
| - |
138 |
| - |
139 |
| - |
140 |
| - |
141 |
| - |
142 |
| - |
143 |
| - |
144 |
| - |
145 |
| - |
146 |
| - |
147 |
| - |
148 |
| - |
149 |
| - |
150 |
| - |
151 |
| - |
152 |
| - |
153 |
| - |
154 |
| - |
155 |
| - |
156 |
| - |
157 |
| - |
158 |
| - |
159 |
| - |
160 |
| - |
161 |
| - |
162 |
| - |
163 |
| - |
164 |
| - |
165 |
| - |
166 |
| - |
167 |
| - |
168 |
| - |
169 |
| - |
170 |
| - |
171 |
| - |
172 |
| - |
173 |
| - |
174 |
| - |
175 |
| - |
176 |
| - |
177 |
| - |
178 |
| - |
179 |
| - |
180 |
| - |
181 |
| - |
182 |
| - |
183 |
| - |
184 |
| - |
185 |
| - |
186 |
| - |
187 |
| - |
188 |
| - |
189 |
| - |
190 |
| - |
191 |
| - |
192 |
| - |
193 |
| - |
194 |
| - |
| 130 | +这编译了遗留代码并且没有发出警告或错误。 这种关闭警告的方法只适用于真正的遗留代码,没有 `Java 5` 中引入的通用功能或其他功能。 也可以使用注释关闭未经 |
| 131 | +检查的警告,如下一节所述,即使使用 `Java 5` 中引入的功能,也可以使用这些警告。 |
195 | 132 |
|
0 commit comments