Skip to content

Commit 93f3371

Browse files
authored
Merge pull request #12 from my-learn/gh-pages-1.0
Gh pages 1.0
2 parents 70a8c83 + 15e85e6 commit 93f3371

File tree

55 files changed

+254
-358
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+254
-358
lines changed

ch07/00_Reflection.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
反射是一组功能的术语,它允许程序检查自己的定义。 `Java` 中的反射在类浏览器,对象检查器,调试器,解释器,服务(如 `JavaBeans™` 和对象序列化)以及任何创
77
建,检查或操作任意 `Java` 对象的工具中发挥作用。
88

9+
910
`Java` 自一开始就出现了反射,但泛型的出现改变了反射的两种重要方式,即为泛型的反射和反射引入了泛型。
1011

1112
通过泛型来进行反射,我们指的是用于反射的一些类型现在是泛型类型。特别是,类 `Class` 成为泛型类 `Class<T>`。这看起来可能会让人感到困惑,但一旦明白它可以
@@ -15,7 +16,10 @@
1516
通过对泛型的反思,我们的意思是反射现在返回有关泛型的信息。有一些新的接口可以表示泛型类型,包括类型变量,参数化类型和通配符类型,还有一些新的方法可以获得
1617
泛型类型的字段,构造函数和方法。
1718

19+
我们依次解释每一个点。我们不承担任何以前的反思知识,但我们专注于与泛型相关的方面。
20+
21+
1822
我们依次解释每一个点。我们不承担任何以前的反思知识,但我们专注于与泛型相关的方面。
1923

2024
《《《 [下一节](01_Generics_for_Reflection.md) <br/>
21-
《《《 [返回首页](../README.md)
25+
《《《 [返回首页](../README.md)

ch07/01_Generics_for_Reflection.md

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33

44
## 反射的泛型
55

6-
`Java` 支持自 `1.0` 版以来的反射以及 `1.1` 版以后的类文字。 它们的核心是 `Class` 类,它表示运行时对象类型的信息。 您可以编写一个类型,后跟
7-
`.class` 作为文字,表示与该类型相对应的类标记,并且方法 `getClass`在每个对象上定义并返回一个类标记,该标记表示该对象在运行时携带的特定类型信息。 这
8-
里是一个例子:
6+
`Java` 支持自 `1.0` 版以来的反射以及 `1.1` 版以后的类文字。 它们的核心是 `Class` 类,它表示运行时对象类型的信息。 您可以编写一个类型,后跟 `.class` 作为文字,表示与该类型相对应的类标记,并且方法 `getClass` 在每个对象上定义并返回一个类标记,该标记表示该对象在运行时携带的特定类型信息。这里是一个例子:
97

108
```java
119
Class ki = Integer.class;
@@ -14,8 +12,7 @@
1412
assert ki == kn;
1513
```
1614

17-
对于给定的类加载器,相同的类型总是由相同的类标记表示。为了强调这一点,在这里我们使用标识符(`==` 运算符)比较类标记。但是,在大多数情况下,使用相等
18-
等于方法)。
15+
对于给定的类加载器,相同的类型总是由相同的类标记表示。为了强调这一点,在这里我们使用标识符(`==` 运算符)比较类标记。但是,在大多数情况下,使用相等 等于方法)。
1916

2017
`Java 5` 中的一个变化是 `Class` 类现在接受一个类型参数,所以 `Class <T>` 是类型 `T` 的类标记的类型。 前面的代码现在写成如下所示:
2118

@@ -63,27 +60,24 @@
6360
Retention r = k.getAnnotation(Retention.class);
6461
```
6562

66-
这种通用类型具有两个优点。 首先,这意味着调用结果不需要强制转换,因为泛型类型系统可以精确地指定正确的类型。 其次,这意味着如果您不小心使用类标记调用
67-
不是 `Annotation` 子类的类的方法,那么会在编译时而不是在运行时检测到。
6863

69-
类标记的另一种用法类似于注释类,它出现在 `java.awt` 包的 `Component` 类的 `getListeners`` 方法中:
64+
这种通用类型具有两个优点。 首先,这意味着调用结果不需要强制转换,因为泛型类型系统可以精确地指定正确的类型。其次,这意味着如果您不小心使用类标记调用不是 `Annotation` 子类的类的方法,那么会在编译时而不是在运行时检测到。
65+
66+
类标记的另一种用法类似于注释类,它出现在 `java.awt` 包的 `Component` 类的 `getListeners` 方法中:
7067

7168
```java
7269
public <T extends EventListener> T[] getListeners(Class<T> listenerType);
7370
```
7471

7572
同样,这意味着 `getListeners` 的代码不需要强制转换,这意味着编译器可以检查该方法是否使用适当类型的类标记调用。
7673

77-
作为类标记的一个有趣用法的最后一个示例,便捷类 `Collections` 包含一个构建包装的方法,该包装检查添加到给定列表或从给定列表中提取的每个元素是否属于给
78-
定类。 (其他集合类也有类似的方法,例如集合和地图。)它具有以下签名:
74+
作为类标记的一个有趣用法的最后一个示例,便捷类 `Collections` 包含一个构建包装的方法,该包装检查添加到给定列表或从给定列表中提取的每个元素是否属于给定类。(其他集合类也有类似的方法,例如集合和地图。)它具有以下签名:
7975

8076
```java
8177
public static <T> List<T> checkedList(List<T> l, Class<T> k)
8278
```
8379

84-
包装在编译时通过动态检查来补充静态检查,这对于提高安全性或与遗留代码的接口(见第 `8.1` 节)可能很有用。 该实现调用前面描述的类 `Class` 中的方法,其
85-
中接收方是传递到方法中的类标记,并且该转换将应用于使用 `get``set``add` 添加到列表中的任何元素,或者将其写入列表中。 然而,`Class<T>` 的类型
86-
参数意味着 `checkedList` 的代码不需要额外的转换(除了调用类类中的 `cast` 方法外),并且编译器可以检查该方法是否使用类标记调用 一个合适的类型。
80+
包装在编译时通过动态检查来补充静态检查,这对于提高安全性或与遗留代码的接口(见第 `8.1` 节)可能很有用。该实现调用前面描述的类 `Class` 中的方法,其中接收方是传递到方法中的类标记,并且该转换将应用于使用 `get``set``add` 添加到列表中的任何元素,或者将其写入列表中。然而,`Class<T>` 的类型参数意味着 `checkedList` 的代码不需要额外的转换(除了调用类类中的 `cast` 方法外),并且编译器可以检查该方法是否使用类标记调用 一个合适的类型。
8781

8882
《《《 [下一节](02_Reflected_Types_are_Reifiable_Types.md) <br/>
89-
《《《 [返回首页](../README.md)
83+
《《《 [返回首页](../README.md)

ch07/02_Reflected_Types_are_Reifiable_Types.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,4 @@
6363
对类别标记的限制导致一个有用的属性。 无论何处出现类型为 `Class<T>` 的类型,类型 `T` 都应该是可重用的类型。 对于 `T[]` 形式的类型也是如此.
6464

6565
《《《 [下一节](03_Reflection_for_Primitive_Types.md) <br/>
66-
《《《 [返回首页](../README.md)
66+
《《《 [返回首页](../README.md)

ch07/03_Reflection_for_Primitive_Types.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@
1818
另一方面,`int[].class` 表示具有基本类型 `integer` 的组件的数组的类标记,并且此类标记的类型为 `Class<int[]>`,这是允许的,因为 `int[]` 是引用类型。
1919

2020
《《《 [下一节](04_A_Generic_Reflection_Library.md) <br/>
21-
《《《 [返回首页](../README.md)
21+
22+
《《《 [返回首页](../README.md)

ch07/04_A_Generic_Reflection_Library.md

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33

44
## 一个通用的反射库
55

6-
正如我们所看到的,粗心使用未经检查的演员阵容可能会导致问题,例如违反广告中的真相原则或不雅暴露原则(参见第 `6.5` 节和第 `6.6` 节)。 最小化使用未经
7-
检查的强制转换的一种技术是将它们封装在库中。 该库可以仔细检查以确保其使用未经检查的强制转换是安全的,而调用该库的代码可以没有未经检查的强制转换。
8-
`Sun` 正在考虑添加类似于这里描述的库方法。
6+
正如我们所看到的,粗心使用未经检查的演员阵容可能会导致问题,例如违反广告中的真相原则或不雅暴露原则(参见第 `6.5` 节和第 `6.6` 节)。 最小化使用未经检查的强制转换的一种技术是将它们封装在库中。 该库可以仔细检查以确保其使用未经检查的强制转换是安全的,而调用该库的代码可以没有未经检查的强制转换。 `Sun` 正在考虑添加类似于这里描述的库方法。
97

108
`7-1` 提供了一个以类型安全的方式使用反射的通用函数库。 它定义了一个包含以下方法的便捷类 `GenericReflection`
119

@@ -16,23 +14,15 @@
1614
public static <T> T[] newArray(T[] a, int size)
1715
```
1816

19-
第一个接受一个对象,找到该对象的类,并返回该类的新实例;这必须与原始对象具有相同的类型。第二个接收数组并返回一个类标记作为其组件类型,如其运行时类型信
20-
息所携带的。相反,第三个分配一个新的数组,其组件类型由给定的类标记和指定的大小指定。第四个接受一个数组和一个大小,并且分配一个与给定数组和给定大小具
21-
有相同组件类型的新数组;它只是构成对前两种方法的调用。前三种方法中的每一种的代码都包含对 `Java` 反射库中一个或两个相应方法的调用,以及对相应返回类型的
22-
未检查转换。
17+
第一个接受一个对象,找到该对象的类,并返回该类的新实例;这必须与原始对象具有相同的类型。第二个接收数组并返回一个类标记作为其组件类型,如其运行时类型信息所携带的。相反,第三个分配一个新的数组,其组件类型由给定的类标记和指定的大小指定。第四个接受一个数组和一个大小,并且分配一个与给定数组和给定大小具有相同组件类型的新数组;它只是构成对前两种方法的调用。前三种方法中的每一种的代码都包含对 `Java` 反射库中一个或两个相应方法的调用,以及对相应返回类型的未检查转换。
2318

24-
由于各种原因,`Java` 反射库中的方法无法返回足够精确的类型,因此需要未经检查的强制转换。方法 `getComponentType` 位于 `Class<T>` 类中,并且 `Java`
25-
无法将方法的签名中的接收方类型限制为 `Class <T[]>`(尽管如果接收方不是类,该调用会引发异常令牌为数组类型)。 `java.lang.reflect.Array` 中的
26-
`newInstance` 方法必须具有返回类型 `Object` 而不是返回类型 `T[]`,因为它可能会返回基本类型的数组。方法 `getClass` 在类型 `T` 的接收器上调用时返回
27-
不是类型为 `Class <? extends T>` 但类型 `Class <?>`,因为需要擦除以确保类令牌始终具有可调整类型。但是,在每种情况下,未经检查的转换都是安全的,用
28-
户可以调用这里定义的四个库例程而不违反铸铁保证。
19+
由于各种原因,`Java` 反射库中的方法无法返回足够精确的类型,因此需要未经检查的强制转换。方法 `getComponentType` 位于 `Class<T>` 类中,并且 `Java` 无法将方法的签名中的接收方类型限制为 `Class <T[]>`(尽管如果接收方不是类,该调用会引发异常令牌为数组类型)。 `java.lang.reflect.Array` 中的 `newInstance` 方法必须具有返回类型 `Object` 而不是返回类型 `T[]`,因为它可能会返回基本类型的数组。方法 `getClass` 在类型 `T` 的接收器上调用时返回不是类型为 `Class <? extends T>` 但类型 `Class <?>`,因为需要擦除以确保类令牌始终具有可调整类型。但是,在每种情况下,未经检查的转换都是安全的,用户可以调用这里定义的四个库例程而不违反铸铁保证。
2920

30-
`7-1`。 用于泛型反射的类型安全库
21+
例7-1。 用于泛型反射的类型安全库
3122

3223
```java
3324
class GenericReflection {
34-
public static <T> T newInstance(T obj) throws InstantiationException, IllegalAccessException,
35-
InvocationTargetException, NoSuchMethodException {
25+
public static <T> T newInstance(T obj) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
3626
Object newobj = obj.getClass().getConstructor().newInstance();
3727
return (T)newobj; // unchecked cast
3828
}
@@ -52,16 +42,11 @@
5242
}
5343
```
5444

55-
第一种方法优先于 `Class.newInstance` 使用 `Constructor.newInstance`(在 `java.lang.reflect` 中),以避免后者出现已知问题。引用 `Sun`
56-
`Class.newInstance` 文档:“请注意,此方法传播由 `nullary` 构造函数抛出的任何异常,包括检查的异常。使用此方法可以有效绕过编译时异常检查,否则编译器
57-
会执行该异常。 `Constructor.newInstance` 方法通过将构造函数抛出的任何异常包装在(`checked``InvocationTargetException` 中来避免此问题。“
45+
第一种方法优先于 `Class.newInstance` 使用 `Constructor.newInstance`(在 `java.lang.reflect` 中),以避免后者出现已知问题。引用 `Sun``Class.newInstance` 文档:“请注意,此方法传播由 `nullary` 构造函数抛出的任何异常,包括检查的异常。使用此方法可以有效绕过编译时异常检查,否则编译器会执行该异常。 `Constructor.newInstance` 方法通过将构造函数抛出的任何异常包装在(`checked``InvocationTargetException` 中来避免此问题。“
5846

59-
第二种方法保证在任何遵循不雅曝光原则和广告真理原则的节目中都能很好地输入。第一个原则保证编译时的组件类型将是可重用的类型,然后第二个原则保证在运行时
60-
返回的通用组件类型必须是在编译时声明的可重用组件类型的子类型。
47+
第二种方法保证在任何遵循不雅曝光原则和广告真理原则的节目中都能很好地输入。第一个原则保证编译时的组件类型将是可重用的类型,然后第二个原则保证在运行时返回的通用组件类型必须是在编译时声明的可重用组件类型的子类型。
6148

62-
如果第三种方法的类参数是基本类型,则会引发非法参数异常。这会捕获以下棘手的情况:如果第一个参数是 `int.class`,那么它的类型是 `Class<Integer>`,但新
63-
数组的类型为 `int[]`,它不是 `Integer[]` 的子类型。如果 `int.class` 具有 `Class<?>` 类型而不是 `Class<Integer>` 类型,则不会出现此问题,如前一
64-
节所述。
49+
如果第三种方法的类参数是基本类型,则会引发非法参数异常。这会捕获以下棘手的情况:如果第一个参数是 `int.class`,那么它的类型是 `Class<Integer>`,但新数组的类型为 `int[]`,它不是 `Integer[]` 的子类型。如果 `int.class` 具有 `Class<?>` 类型而不是 `Class<Integer>` 类型,则不会出现此问题,如前一节所述。
6550

6651
作为使用第一种方法的一个例子,下面是一个方法,它将一个集合复制到一个相同类型的新集合中,从而保留参数的类型:
6752

@@ -86,8 +71,7 @@
8671
}
8772
```
8873

89-
一般来说,我们建议如果您需要使用未经检查的强制转换,那么您应该将它们封装到少数库方法中,就像我们在这里所做的那样。 不要让未经检查的代码在您的程序中激
90-
增!
74+
一般来说,我们建议如果您需要使用未经检查的强制转换,那么您应该将它们封装到少数库方法中,就像我们在这里所做的那样。 不要让未经检查的代码在您的程序中激增!
9175

9276
《《《 [下一节](05_Reflection_for_Generics.md) <br/>
93-
《《《 [返回首页](../README.md)
77+
《《《 [返回首页](../README.md)

ch07/05_Reflection_for_Generics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,4 @@
8585
部分解释如何访问它。
8686

8787
《《《 [下一节](06_Reflecting_Generic_Types.md) <br/>
88-
《《《 [返回首页](../README.md)
88+
《《《 [返回首页](../README.md)

ch07/06_Reflecting_Generic_Types.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919

2020
方法可用于将类的超类和超接口作为类型返回,并访问字段的泛型类型,构造函数的参数类型以及方法的参数和结果类型。
2121

22-
您还可以提取代表类或接口声明或泛型方法或构造函数的形式参数的类型变量。类型变量的类型需要一个参数,并写入 `TypeVariable<D>`,其中 `D` 表示声明类型变
23-
量的对象的类型。因此,类的类型变量具有类型 `TypeVariable<Class<?>>`,而泛型方法的类型变量具有类型 `TypeVariable<Method>`。可以说,类型参数是令人
24-
困惑的,并不是非常有用。由于它对 `6.6` 节中描述的问题负责,因此 `Sun` 可能会在将来删除它。
22+
您还可以提取代表类或接口声明或泛型方法或构造函数的形式参数的类型变量。类型变量的类型需要一个参数,并写入 `TypeVariable<D>`,其中 `D` 表示声明类型变量的对象的类型。因此,类的类型变量具有类型 `TypeVariable<Class<?>>`,而泛型方法的类型变量具有类型 `TypeVariable<Method>`。可以说,类型参数是令人困惑的,并不是非常有用。由于它对 `6.6` 节中描述的问题负责,因此 `Sun` 可能会在将来删除它。
2523

2624
`7-5` 使用这些方法打印出与类关联的所有标题信息。这里有两个使用例子:
2725

ch08/00_Effective_Generics.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](../ch07/06_Reflecting_Generic_Types.md)
3+
14
## 有效的泛型
25

3-
本章包含如何在实际编码中有效使用泛型的建议。 我们考虑检查集合,安全问题,专用类和二进制兼容性。 本节的标题是对 `Joshua Bloch` 的着作 `Effective Java(Addison-Wesley)`的致敬。
6+
本章包含如何在实际编码中有效使用泛型的建议。 我们考虑检查集合,安全问题,专用类和二进制兼容性。 本节的标题是对 `Joshua Bloch` 的着作 `Effective Java(Addison-Wesley)` 的致敬。
7+
8+
《《《 [下一节](01_Take_Care_when_Callin_Legacy_Code.md) <br/>
9+
《《《 [返回首页](../README.md)

ch08/01_Take_Care_when_Callin_Legacy_Code.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](00_Effective_Generics.md)
3+
14
## 调用遗留代码时要小心
25

36
正如我们所看到的,泛型类型在编译时被检查,而不是运行时。 通常,这正是我们想要的,因为在编译时检查会更早地报告错误,并且不会导致运行时开销。 但是,有时这可能不合适,因为我们无法确定编译时检查是否足够(比如说,因为我们将参数化类型的实例传递给旧客户端或我们不信任的客户端 ),还是因为我们在运行时需要关于类型的信息(比如说,因为我们需要一个可重用类型作为数组组件)。 一个托收集合通常会诀窍,如果不行,我们可以创建一个专门的类。 我们考虑本节中的已检查集合,下一节中的安全问题以及之后的部分中的专门类。
@@ -59,7 +62,8 @@
5962

6063
仅当列表元素具有可确定类型时,检查列表才提供有用的保证。 如果你想在列表不是可确定类型时应用这些技术,你可能需要考虑应用 `8.3` 节的专门化技术。
6164

62-
65+
《《《 [下一节](02_Use_Checked_Collections_to_Enforce_Security.md) <br/>
66+
《《《 [返回首页](../README.md)
6367

6468

6569

ch08/02_Use_Checked_Collections_to_Enforce_Security.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
《《《 [返回首页](../README.md) <br/>
2+
《《《 [上一节](01_Take_Care_when_Callin_Legacy_Code.md)
3+
14
## 使用选中的集合来强化安全性
25

36
请注意,通用类型提供的保证仅适用于没有未经检查的警告的情况。 这意味着泛型类型对于确保其他人编写的代码的安全性没有用处,因为您无法知道该代码是否在编译时引发未经检查的警告。
@@ -65,7 +68,8 @@
6568

6669
选中的集合不是实施安全性的唯一技术。 如果提供订单的接口返回一个列表而不是接受一个列表,那么代理可以使用前一节中的空循环技术来确保列表只包含经过授权的订单,然后才能通过它们。 也可以使用专业化,如下一节所述,创建一个特殊类型的列表,只能包含授权订单。
6770

68-
71+
《《《 [下一节](03_Specialize_to_Create_Reifiable_Types.md) <br/>
72+
《《《 [返回首页](../README.md)
6973

7074

7175

0 commit comments

Comments
 (0)