|
11 | 11 | `Object` 类的克隆方法说明了协变覆盖的优点:
|
12 | 12 |
|
13 | 13 | ```java
|
14 |
| - class Object { |
15 |
| - ... |
16 |
| - public Object clone() { ... } |
17 |
| - } |
| 14 | +class Object { |
| 15 | + ... |
| 16 | + public Object clone() { ... } |
| 17 | +} |
18 | 18 | ```
|
19 | 19 |
|
20 | 20 | 在 `Java 1.4` 中,任何覆盖 `clone` 的类都必须给它完全相同的返回类型,即 `Object`:
|
21 | 21 |
|
22 | 22 | ```java
|
23 |
| - class Point { |
24 |
| - public int x; |
25 |
| - public int y; |
26 |
| - public Point(int x, int y) { this.x=x; this.y=y; } |
27 |
| - public Object clone() { return new Point(x,y); } |
28 |
| - } |
| 23 | +class Point { |
| 24 | + public int x; |
| 25 | + public int y; |
| 26 | + public Point(int x, int y) { this.x=x; this.y=y; } |
| 27 | + public Object clone() { return new Point(x,y); } |
| 28 | +} |
29 | 29 | ```
|
30 | 30 |
|
31 | 31 | 在这里,尽管克隆总是返回一个 `Point`,但规则要求它具有返回类型 `Object`。 这很烦人,因为每次克隆的调用都必须输出结果。
|
32 | 32 |
|
33 | 33 | ```java
|
34 |
| - Point p = new Point(1,2); |
35 |
| - Point q = (Point)p.clone(); |
| 34 | + Point p = new Point(1,2); |
| 35 | + Point q = (Point)p.clone(); |
36 | 36 | ```
|
37 | 37 |
|
38 | 38 | 在 `Java 5` 中,可以给克隆方法一个更重要的返回类型:
|
39 | 39 |
|
40 | 40 | ```java
|
41 |
| - class Point { |
42 |
| - public int x; |
43 |
| - public int y; |
44 |
| - public Point(int x, int y) { this.x=x; this.y=y; } |
45 |
| - public Point clone() { return new Point(x,y); } |
46 |
| - } |
| 41 | +class Point { |
| 42 | + public int x; |
| 43 | + public int y; |
| 44 | + public Point(int x, int y) { this.x=x; this.y=y; } |
| 45 | + public Point clone() { return new Point(x,y); } |
| 46 | +} |
47 | 47 | ```
|
48 | 48 |
|
49 | 49 | 现在我们可以克隆没有转换:
|
50 | 50 |
|
51 | 51 | ```java
|
52 |
| - Point p = new Point(1,2); |
53 |
| - Point q = p.clone(); |
| 52 | + Point p = new Point(1,2); |
| 53 | + Point q = p.clone(); |
54 | 54 | ```
|
55 | 55 |
|
56 | 56 | 协变覆盖使用前一节中描述的桥接技术来实现。 和以前一样,如果您应用反射,您可以看到桥。 这里是在类 `Point` 中找到名称为 `clone` 的所有方法的代码:
|
57 | 57 |
|
58 | 58 | ```java
|
59 |
| - for (Method m : Point.class.getMethods()) |
60 |
| - if (m.getName().equals("clone")) |
61 |
| - System.out.println(m.toGenericString()); |
| 59 | +for (Method m : Point.class.getMethods()) |
| 60 | + if (m.getName().equals("clone")) |
| 61 | + System.out.println(m.toGenericString()); |
62 | 62 | ```
|
63 | 63 |
|
64 | 64 | 在Point类的协变版本上运行此代码会产生以下输出:
|
65 | 65 |
|
66 | 66 | ```java
|
67 |
| - public Point Point.clone() |
68 |
| - public bridge java.lang.Object Point.clone() |
| 67 | + public Point Point.clone() |
| 68 | + public bridge java.lang.Object Point.clone() |
69 | 69 | ```
|
70 | 70 |
|
71 | 71 | 这里桥接技术利用了这样一个事实,即在类文件中,同一类的两个方法可能具有相同的参数签名,尽管这在 `Java` 源代码中是不允许的。 桥接方法只是简单地调用第一
|
|
0 commit comments