Skip to content

Commit f9efd43

Browse files
authored
Merge pull request #6 from maskleo-learning/gh-pages-1.0
Gh pages 1.0
2 parents 007e9cc + 7d84dd4 commit f9efd43

5 files changed

+56
-144
lines changed

ch03/07_Bridges.md

+18-44
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](06_Multiple_Bounds.md)
3+
14
## 桥梁
25

3-
正如我们前面提到的,泛型是通过擦除来实现的:当你用泛型编写代码时,它的编译方式几乎与没有泛型编写的代码完全相同。在参数化接口(如 `Comparable<T>`)的情况下,这可能会导致编译器插入其他方法;这些附加的方法被称为网桥。
6+
正如我们前面提到的,泛型是通过擦除来实现的:当你用泛型编写代码时,它的编译方式几乎与没有泛型编写的代码完全相同。在参数化接口(如 `Comparable<T>`)的
7+
情况下,这可能会导致编译器插入其他方法;这些附加的方法被称为网桥。
48

5-
示例 `3-6` 显示了 `Comparable` 接口以及泛型之前的 `Java` 中的 `Integer` 类的简化版本。在非通用接口中,`compareTo` 方法接受一个 `Object` 类型的参数。在非泛型类中,有两个 `compareTo` 方法。第一个是您可能期望的简单方法,用于将整数与另一个整数进行比较。第二个将整数与任意对象进行比较:它将该对象转换为整数并调用第一个方法。第二种方法对于重写 `Comparable` 接口中的 `compareTo` 方法是必需的,因为只有当方法签名相同时才会覆盖。这第二种方法被称为桥梁。
9+
示例 `3-6` 显示了 `Comparable` 接口以及泛型之前的 `Java` 中的 `Integer` 类的简化版本。在非通用接口中,`compareTo` 方法接受一个 `Object` 类型的
10+
参数。在非泛型类中,有两个 `compareTo` 方法。第一个是您可能期望的简单方法,用于将整数与另一个整数进行比较。第二个将整数与任意对象进行比较:它将该对
11+
象转换为整数并调用第一个方法。第二种方法对于重写 `Comparable` 接口中的 `compareTo` 方法是必需的,因为只有当方法签名相同时才会覆盖。这第二种方法被称
12+
为桥梁。
613

7-
`3-7` 显示了当 `Comparable` 接口和 `Integer` 类被基因化时发生了什么。在通用接口中,`compareTo` 方法接受 `T` 类型的参数。在泛型类中,单个 `compareTo` 方法接受 `Integer` 类型的参数。
14+
`3-7` 显示了当 `Comparable` 接口和 `Integer` 类被基因化时发生了什么。在通用接口中,`compareTo` 方法接受 `T` 类型的参数。在泛型类中,单个
15+
`compareTo` 方法接受 `Integer` 类型的参数。
816

917
桥接方法由编译器自动生成。 事实上,这两个示例的编译版本的代码基本相同。
1018

11-
例3-6。 传统的可比较整数的代码
19+
`3-6`。 传统的可比较整数的代码
1220

1321
```java
1422
interface Comparable {
@@ -26,7 +34,7 @@
2634
}
2735
```
2836

29-
例3-7。 可比较整数的通用代码
37+
`3-7`。 可比较整数的通用代码
3038

3139
```java
3240
interface Comparable<T> {
@@ -49,51 +57,17 @@
4957
System.out.println(m.toGenericString());
5058
```
5159

52-
在通用版本的Integer类上运行此代码会产生以下输出
60+
在通用版本的 `Integer` 类上运行此代码会产生以下输出
5361

5462
```java
5563
public int Integer.compareTo(Integer)
5664
public bridge int Integer.compareTo(java.lang.Object)
5765
```
5866

59-
这确实包含两种方法,一种是采用 `Integer` 类型参数的声明方法,另一种是采用 `Object` 类型参数的桥接方法。 (截至撰写本文时,`Sun JVM` 打印的是 `volatile` 而不是 `bridge`,因为`Java` 字节码中用于指示网桥方法的位也用于指示易失性字段;预计此错误将在未来版本中得到修复。)
67+
这确实包含两种方法,一种是采用 `Integer` 类型参数的声明方法,另一种是采用 `Object` 类型参数的桥接方法。 (截至撰写本文时,`Sun JVM` 打印的是
68+
`volatile` 而不是 `bridge`,因为`Java` 字节码中用于指示网桥方法的位也用于指示易失性字段;预计此错误将在未来版本中得到修复。)
6069

6170
将旧版代码转换为使用泛型时,网桥可以发挥重要作用; 见 `8.4` 节。
6271

63-
64-
65-
66-
67-
68-
69-
70-
71-
72-
73-
74-
75-
76-
77-
78-
79-
80-
81-
82-
83-
84-
85-
86-
87-
88-
89-
90-
91-
92-
93-
94-
95-
96-
97-
98-
99-
72+
《《《 [下一节](08_Covariant_Overriding.md) <br/>
73+
《《《 [返回首页](../README.md)

ch03/08_Covariant_Overriding.md

+9-40
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](07_Bridges.md)
3+
14
## 协变覆盖
25

36
`Java 5` 支持协变方法重写。 这个特性与泛型没有直接关系,但我们在这里提到它,因为它值得了解,并且因为它使用了上一节中描述的桥接技术来实现。
47

5-
`Java 1.4` 及更早版本中,只有参数和返回类型完全匹配时,一个方法才能覆盖另一个方法。 在 `Java 5` 中,如果参数类型完全匹配,并且重写方法的返回类型是另一个方法的返回类型的子类型,则方法可以重写另一个方法。
8+
`Java 1.4` 及更早版本中,只有参数和返回类型完全匹配时,一个方法才能覆盖另一个方法。 在 `Java 5` 中,如果参数类型完全匹配,并且重写方法的返回类型
9+
是另一个方法的返回类型的子类型,则方法可以重写另一个方法。
610

711
`Object` 类的克隆方法说明了协变覆盖的优点:
812

@@ -64,43 +68,8 @@
6468
public bridge java.lang.Object Point.clone()
6569
```
6670

67-
这里桥接技术利用了这样一个事实,即在类文件中,同一类的两个方法可能具有相同的参数签名,尽管这在 `Java` 源代码中是不允许的。 桥接方法只是简单地调用第一种方法。 (同样,在撰写本文时,`Sun JVM` 打印出的是 `volatile` 而不是桥。)
68-
69-
70-
71-
72-
73-
74-
75-
76-
77-
78-
79-
80-
81-
82-
83-
84-
85-
86-
87-
88-
89-
90-
91-
92-
93-
94-
95-
96-
97-
98-
99-
100-
101-
102-
103-
104-
105-
71+
这里桥接技术利用了这样一个事实,即在类文件中,同一类的两个方法可能具有相同的参数签名,尽管这在 `Java` 源代码中是不允许的。 桥接方法只是简单地调用第一
72+
种方法。 (同样,在撰写本文时,`Sun JVM` 打印出的是 `volatile` 而不是桥。)
10673

74+
《《《 [下一节](../ch04/00_Declarations.md) <br/>
75+
《《《 [返回首页](../README.md)

ch04/00_Declarations.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](../ch03/08_Covariant_Overriding.md)
3+
14
# 声明
25

3-
本章讨论如何声明一个通用类。 它描述了构造函数,静态成员和嵌套类,它填补了擦除工作的一些细节。
6+
本章讨论如何声明一个通用类。 它描述了构造函数,静态成员和嵌套类,它填补了擦除工作的一些细节。
7+
8+
《《《 [下一节](01_Constructors.md) <br/>
9+
《《《 [返回首页](../README.md)

ch04/01_Constructors.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](00_Declarations.md)
3+
14
## 构造函数
25

36
在泛型类中,类型参数出现在声明类的头中,但不在构造函数中:
@@ -19,10 +22,14 @@
1922
assert pair.getFirst().equals("one") && pair.getSecond() == 2;
2023
```
2124

22-
**注意这一点!**一个常见的错误是在调用构造函数时忘记类型参数:
25+
__注意这一点!__ 一个常见的错误是在调用构造函数时忘记类型参数:
2326

2427
```java
2528
Pair<String, Integer> pair = new Pair("one",2);
2629
```
2730

28-
这个错误会产生警告,但不会产生错误。 它被认为是合法的,因为 `Pair` 被视为原始类型,但是从原始类型转换为相应的参数化类型会生成未经检查的警告; 见 `5.3` 节,它解释了 `-Xlint:unchecked` 标志如何帮助你发现这种错误。
31+
这个错误会产生警告,但不会产生错误。 它被认为是合法的,因为 `Pair` 被视为原始类型,但是从原始类型转换为相应的参数化类型会生成未经检查的警告; 见 `5.3`
32+
节,它解释了 `-Xlint:unchecked` 标志如何帮助你发现这种错误。
33+
34+
《《《 [下一节](02_Static_Members.md) <br/>
35+
《《《 [返回首页](../README.md)

ch04/02_Static_Members.md

+13-57
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](01_Constructors.md)
3+
14
## 静态成员
25

3-
因为泛型是通过擦除编译的,所以在运行时类`List<Integer>``List<String>``List<List<String>>` 全部由一个类实现,即 `List`。你可以看到这个使用反射:
6+
因为泛型是通过擦除编译的,所以在运行时类`List<Integer>``List<String>``List<List<String>>` 全部由一个类实现,即 `List`。你可以看到这个使用
7+
反射:
48

59
```java
610
List<Integer> ints = Arrays.asList(1,2,3);
@@ -10,7 +14,8 @@
1014

1115
这里在运行时与整数列表关联的类与与字符串列表关联的类相同。
1216

13-
其中一个结果是泛型类的静态成员在该类的所有实例上共享,包括不同类型的实例。 类的静态成员不能引用泛型类的类型参数,并且在访问静态成员时,不应该对类名称进行参数化。
17+
其中一个结果是泛型类的静态成员在该类的所有实例上共享,包括不同类型的实例。 类的静态成员不能引用泛型类的类型参数,并且在访问静态成员时,不应该对类名称
18+
进行参数化。
1419

1520
例如,下面是一个类 `Cell<T>`,其中每个单元格都有一个整型标识符和一个类型为 `T` 的值:
1621

@@ -27,7 +32,8 @@
2732
}
2833
```
2934

30-
静态字段 `count` 用于为每个单元分配不同的标识符。 静态 `nextId` 方法被同步,以确保即使在多个线程的情况下也能生成唯一的标识符。 静态 `getCount` 方法返回当前计数。
35+
静态字段 `count` 用于为每个单元分配不同的标识符。 静态 `nextId` 方法被同步,以确保即使在多个线程的情况下也能生成唯一的标识符。 静态 `getCount`
36+
法返回当前计数。
3137

3238
这里是分配包含字符串的单元格和包含整数的单元格的代码,它们分别分配了标识符 `0``1`
3339

@@ -61,7 +67,8 @@
6167
}
6268
```
6369

64-
由于类可能在不同的地方使用不同的类型参数,因此在声明静态字段值或静态方法 `getValues()` 时引用 `T` 是没有意义的,并且这些行在编译时会报告为错误。如果我们想要一个单元格中保存的所有值的列表,那么我们需要使用一个对象列表,如下面的变体所示:
70+
由于类可能在不同的地方使用不同的类型参数,因此在声明静态字段值或静态方法 `getValues()` 时引用 `T` 是没有意义的,并且这些行在编译时会报告为错误。如果
71+
我们想要一个单元格中保存的所有值的列表,那么我们需要使用一个对象列表,如下面的变体所示:
6572

6673
```java
6774
class Cell2<T> {
@@ -81,56 +88,5 @@
8188
assert Cell2.getValues().toString().equals("[one, 2]");
8289
```
8390

84-
85-
86-
87-
88-
89-
90-
91-
92-
93-
94-
95-
96-
97-
98-
99-
100-
101-
102-
103-
104-
105-
106-
107-
108-
109-
110-
111-
112-
113-
114-
115-
116-
117-
118-
119-
120-
121-
122-
123-
124-
125-
126-
127-
128-
129-
130-
131-
132-
133-
134-
135-
136-
91+
《《《 [下一节](03_Nested_Classes.md) <br/>
92+
《《《 [返回首页](../README.md)

0 commit comments

Comments
 (0)