Skip to content

Commit 4e5dd70

Browse files
committed
add 机器翻译
Signed-off-by: maskleo <masque@aliyun.com>
1 parent 68d9b94 commit 4e5dd70

4 files changed

+78
-0
lines changed

ch05/00_Evolution_Not_Revolution.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
## 进化,而不是革命
2+
3+
支持 `Java` 泛型设计的一个格言是进化,而不是革命。必须有可能迁移大量现有的代码,逐步使用泛型(演化),而不需要进行一次性的全面变革(革命)。泛型设计可确保旧代码针对新的 `Java` 库进行编译,避免了一半代码需要旧库和一半代码需要新库的不幸情况。
4+
5+
进化要求比通常的向后兼容要强得多。通过简单的向后兼容性,可以为每个应用程序提供传统版本和通用版本;例如,这正是 `C#` 中发生的情况。如果您正在构建由多个供应商提供的代码之上,其中一些人使用旧版集合,其中一些人使用通用集合,这可能会迅速导致版本化的噩梦。
6+
7+
我们要求的是相同的客户端代码可以同时适用于库的传统版本和通用版本。这意味着图书馆的供应商和客户可以完全独立地选择何时从传统代码转换为通用代码。这比后向兼容性要求强得多;它被称为迁移兼容性或平台兼容性。
8+
9+
`Java` 通过擦除来实现泛型,这可以确保传统版本和通用版本通常会生成相同的类文件,并保存一些有关类型的辅助信息。可以用通用类文件替换旧类文件而不更改甚至重新编译任何客户端码;这被称为二进制兼容性。
10+
11+
我们总结这与座右铭二进制兼容性确保迁移兼容性- 或者更简洁一点,擦除可以简化演变过程。
12+
13+
本节介绍如何将泛型添加到现有代码;它考虑了一个小例子,一个用于扩展集合框架的堆栈库以及一个关联的客户端。我们从传统堆栈库和客户端(在泛型之前为Java编写)开始,然后展示相应的通用库和客户端(为泛型编写的 `Java`)。我们的示例代码很小,因此很容易一次性更新为泛型,但实际上库和客户端会更大,我们可能需要分别进行演变。这是原始类型的帮助,它们是参数化类型的传统对应物。
14+
15+
程序的各个部分可以按照任意顺序进行演变。你可能有一个遗留客户端的通用库;对于那些使用 `Java 5`中的集合框架和遗留代码的人来说,这是常见的情况。或者你可能有一个通用客户端的遗留库;这种情况下,您希望为库提供通用签名而不需要重写整个库。我们考虑三种方法来做到这一点:对源代码,存根文件和包装器进行最小限度的更改。当你有权访问源代码时,第一个是有用的,第二个是不用的;我们建议不要第三个。
16+
17+
在实践中,类库和客户端可能涉及很多接口和类,甚至可能在图书馆和客户端之间没有明确的区别。但是这里讨论的相同原则仍然适用,并且可以用来独立于任何其他部分发展程序的任何部分。
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
## 旧版客户端的旧版库
2+
3+
4+
我们从一个简单的栈库和一个关联的客户端开始,如例 `5-1`所示。这是为 `Java 1.4`及其版本的集合框架编写的遗留代码。像集合框架一样,我们将库构造为接口 `Stack`(类似于 `List`),实现类 `ArrayStack`(类似于 `ArrayList`)和实用类 `Stacks`(类似于 `Collections`)。接口堆栈提供了三种方法:空,推送和弹出。实现类 `ArrayStack` 提供了一个没有参数的构造函数,并使用方法 `size``add``remove` 在列表上实现了方法 `empty``push``pop`。流行的主体可以更短 - 而不是将值分配给变量,它可以直接返回 - 但是随着代码的发展,变量的类型如何变化会很有趣。实用程序类只提供一种方法,反向,它从一个堆栈重复弹出并推向另一个堆栈。
5+
6+
客户端分配一个堆栈,向其中推入一些整数,然后弹出一个整数,然后将其余的余数转换为新的堆栈。由于这是 `Java 1.4`,所以整数必须在传递到 `push` 时显式装箱,并且在由 `pop` 返回时显式解除装箱。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
## 具有通用客户端的通用库
2+
3+
接下来,我们更新库和客户端以使用泛型,如例 `5-2` 中所示。 这是用于 `Java 5` 及其集合版框架的通用代码。 接口现在接受一个类型参数,变成 `Stack<E>`(类似于 `List<E>`),实现类也变为 `ArrayStack<E>`(类似于 `ArrayList<E>`),但没有添加类型参数 实用工具类 `Stacks`(类似于 `Collections`)。 `push``pop` 的签名和主体中的 `Object` 类型由类型参数 `E` 替换。 请注意,`ArrayStack` 中的构造函数不需要类型参数。 在实用程序类中,反向方法变为带有参数和 `Stack<T>` 类型结果的泛型方法。 适当的类型参数被添加到客户端,现在隐式装箱和取消装箱。
4+
5+
简而言之,转换过程非常简单:只需添加一些类型参数,并用适当的类型变量替换 `Object` 的出现即可。 通过比较两个示例中突出显示的部分,可以发现传统版本和通用版本之间的所有差异。 泛型的实现设计为使两个版本生成基本上相同的类文件。 有些类型的辅助信息可能会有所不同,但要执行的实际字节码将是相同的。 因此,执行遗留版本和通用版本会产生相同的结果。 正如我们接下来讨论的那样,传统和普通资源产生相同类文件的事实可以简化进化过程。
6+
7+
`5-1`。 传统客户端的旧版库
8+
9+
```java
10+
l/Stack.java:
11+
interface Stack {
12+
public boolean empty();
13+
public void push(Object elt);
14+
public Object pop();
15+
}
16+
l/ArrayStack.java:
17+
import java.util.*;
18+
class ArrayStack implements Stack {
19+
private List list;
20+
public ArrayStack() { list = new ArrayList(); }
21+
public boolean empty() { return list.size() == 0; }
22+
public void push(Object elt) { list.add(elt); }
23+
public Object pop() {
24+
Object elt = list.remove(list.size()-1);
25+
return elt;
26+
}
27+
public String toString() { return "stack"+list.toString(); }
28+
}
29+
l/Stacks.java:
30+
class Stacks {
31+
public static Stack reverse(Stack in) {
32+
Stack out = new ArrayStack();
33+
while (!in.empty()) {
34+
Object elt = in.pop();
35+
out.push(elt);
36+
}
37+
return out;
38+
}
39+
}
40+
l/Client.java:
41+
class Client {
42+
public static void main(String[] args) {
43+
Stack stack = new ArrayStack();
44+
for (int i = 0; i<4; i++) stack.push(new Integer(i));
45+
assert stack.toString().equals("stack[0, 1, 2, 3]");
46+
int top = ((Integer)stack.pop()).intValue();
47+
assert top == 3 && stack.toString().equals("stack[0, 1, 2]");
48+
Stack reverse = Stacks.reverse(stack);
49+
assert stack.empty();
50+
assert reverse.toString().equals("stack[2, 1, 0]");
51+
}
52+
}
53+
```
54+

ch05/03_Generic_Library_with_Legacy_Client.md

Whitespace-only changes.

0 commit comments

Comments
 (0)