File tree Expand file tree Collapse file tree 7 files changed +50
-135
lines changed Expand file tree Collapse file tree 7 files changed +50
-135
lines changed Original file line number Diff line number Diff line change 33
44## 反射
55
6- 反射是一组功能的术语,它允许程序检查自己的定义。 ` Java ` 中的反射在类浏览器,对象检查器,调试器,解释器,服务(如 ` JavaBeans™ ` 和对象序列化)以及任何创建,检查或操作任意Java对象的工具中发挥作用。
6+ 反射是一组功能的术语,它允许程序检查自己的定义。 ` Java ` 中的反射在类浏览器,对象检查器,调试器,解释器,服务(如 ` JavaBeans™ ` 和对象序列化)以及任何创
7+ 建,检查或操作任意 ` Java ` 对象的工具中发挥作用。
8+
79
810` Java ` 自一开始就出现了反射,但泛型的出现改变了反射的两种重要方式,即为泛型的反射和反射引入了泛型。
911
10- 通过泛型来进行反射,我们指的是用于反射的一些类型现在是泛型类型。特别是,类 ` Class ` 成为泛型类 ` Class<T> ` 。这看起来可能会让人感到困惑,但一旦明白它可以使得使用反射的程序更加清晰。类文字和方法 ` Object.getClass ` 使用特殊技巧来返回更精确的类型信息。泛型被用来在注释的反映中特别有效。我们观察到 ` Class<T> ` 中的类型参数 ` T ` 应该总是绑定到一个可定义类型,并且我们提供一个简短的库,可以帮助您避免许多常见的未经检查的强制转换。
12+ 通过泛型来进行反射,我们指的是用于反射的一些类型现在是泛型类型。特别是,类 ` Class ` 成为泛型类 ` Class<T> ` 。这看起来可能会让人感到困惑,但一旦明白它可以
13+ 使得使用反射的程序更加清晰。类文字和方法 ` Object.getClass ` 使用特殊技巧来返回更精确的类型信息。泛型被用来在注释的反映中特别有效。我们观察到
14+ ` Class<T> ` 中的类型参数 ` T ` 应该总是绑定到一个可定义类型,并且我们提供一个简短的库,可以帮助您避免许多常见的未经检查的强制转换。
15+
16+ 通过对泛型的反思,我们的意思是反射现在返回有关泛型的信息。有一些新的接口可以表示泛型类型,包括类型变量,参数化类型和通配符类型,还有一些新的方法可以获得
17+ 泛型类型的字段,构造函数和方法。
18+
19+ 我们依次解释每一个点。我们不承担任何以前的反思知识,但我们专注于与泛型相关的方面。
1120
12- 通过对泛型的反思,我们的意思是反射现在返回有关泛型的信息。有一些新的接口可以表示泛型类型,包括类型变量,参数化类型和通配符类型,还有一些新的方法可以获得泛型类型的字段,构造函数和方法。
1321
1422我们依次解释每一个点。我们不承担任何以前的反思知识,但我们专注于与泛型相关的方面。
1523
Original file line number Diff line number Diff line change 2323 assert ki == kn;
2424```
2525
26- 类标记和 ` getClass ` 方法由编译器专门处理。 通常,如果T是一个没有类型参数的类型,那么 ` T.class ` 的类型为 ` Class<T> ` ,并且如果 ` e ` 是 ` T ` 类型的表达式,那么 ` e.getClass() ` 的类型为 ` Class<? extends T> ` 。 (我们将看到 ` T ` 在下一节中有类型参数时会发生什么。)通配符是必需的,因为变量引用的对象的类型可能是变量类型的子类型,在这种情况下, 其中 ` Number ` 类型的变量包含 ` Integer ` 类型的对象。
26+ 类标记和 ` getClass ` 方法由编译器专门处理。 通常,如果T是一个没有类型参数的类型,那么 ` T.class ` 的类型为 ` Class<T> ` ,并且如果 ` e ` 是 ` T ` 类型的表
27+ 达式,那么 ` e.getClass() ` 的类型为 ` Class<? extends T> ` 。 (我们将看到 ` T ` 在下一节中有类型参数时会发生什么。)通配符是必需的,因为变量引用的对象
28+ 的类型可能是变量类型的子类型,在这种情况下, 其中 ` Number ` 类型的变量包含 ` Integer ` 类型的对象。
2729
28- 对于反射的许多用途,您不会知道类标记的确切类型(如果您确实需要,您可能不需要使用反射),并且在这些情况下,您可以使用 ` Class<?> ` 编写类型,使用 一个无界的通配符。 但是,在某些情况下,类型参数提供的类型信息是无价的,就像我们在 ` 6.5 ` 节中讨论的 ` toArray ` 的变体一样:
30+ 对于反射的许多用途,您不会知道类标记的确切类型(如果您确实需要,您可能不需要使用反射),并且在这些情况下,您可以使用 ` Class<?> ` 编写类型,使用 一个
31+ 无界的通配符。 但是,在某些情况下,类型参数提供的类型信息是无价的,就像我们在 ` 6.5 ` 节中讨论的 ` toArray ` 的变体一样:
2932
3033``` java
3134 public static < T > T [] toArray(Collection<T > c, Class<T > k)
4750 }
4851```
4952
50- 第一个返回该类的新实例,当然这个实例的类型为 ` T ` 。 第二个将任意对象转换为接收者类,因此它会抛出类抛出异常或返回类型 ` T ` 的结果。 第三个返回超类,它必须具有指定的类型。 第四个检查接收者类是参数类的一个子类,并且引发一个类转换异常或者返回接收者适当改变的类型。
53+ 第一个返回该类的新实例,当然这个实例的类型为 ` T ` 。 第二个将任意对象转换为接收者类,因此它会抛出类抛出异常或返回类型 ` T ` 的结果。 第三个返回超类,它
54+ 必须具有指定的类型。 第四个检查接收者类是参数类的一个子类,并且引发一个类转换异常或者返回接收者适当改变的类型。
5155
52- 第五和第六种方法是新注释工具的一部分。 这些方法很有趣,因为它们显示了如何使用类的类型参数来取得良好效果。 例如,保留是注释的一个子类,因此您可以按如下方式在类 ` k ` 上提取保留注释:
56+ 第五和第六种方法是新注释工具的一部分。 这些方法很有趣,因为它们显示了如何使用类的类型参数来取得良好效果。 例如,保留是注释的一个子类,因此您可以按如
57+ 下方式在类 ` k ` 上提取保留注释:
5358
5459``` java
5560 Retention r = k. getAnnotation(Retention . class);
5661```
5762
63+
5864这种通用类型具有两个优点。 首先,这意味着调用结果不需要强制转换,因为泛型类型系统可以精确地指定正确的类型。其次,这意味着如果您不小心使用类标记调用不是 ` Annotation ` 子类的类的方法,那么会在编译时而不是在运行时检测到。
5965
6066类标记的另一种用法类似于注释类,它出现在 ` java.awt ` 包的 ` Component ` 类的 ` getListeners ` 方法中:
7480包装在编译时通过动态检查来补充静态检查,这对于提高安全性或与遗留代码的接口(见第 ` 8.1 ` 节)可能很有用。该实现调用前面描述的类 ` Class ` 中的方法,其中接收方是传递到方法中的类标记,并且该转换将应用于使用 ` get ` ,` set ` 或 ` add ` 添加到列表中的任何元素,或者将其写入列表中。然而,` Class<T> ` 的类型参数意味着 ` checkedList ` 的代码不需要额外的转换(除了调用类类中的 ` cast ` 方法外),并且编译器可以检查该方法是否使用类标记调用 一个合适的类型。
7581
7682《《《 [ 下一节] ( 02_Reflected_Types_are_Reifiable_Types.md ) <br />
77- 《《《 [ 返回首页] ( ../README.md )
78-
79-
80-
81-
82-
83-
84-
85-
86-
87-
88-
89-
90-
91-
92-
93-
94-
95-
96-
97-
83+ 《《《 [ 返回首页] ( ../README.md )
Original file line number Diff line number Diff line change 1414
1515这里整型的类型列表和字符串的类型列表都由同一个类标记表示,其中的类文字被写入 ` ArrayList.class ` 。
1616
17- 由于该类始终表示可重用类型,因此使用不可赋予的类型对类 ` Class ` 进行参数化没有意义。 因此,使用类型参数生成类的两种主要方法(即 ` getClass ` 方法和类文本)都被设计为在所有情况下都为类型参数生成可重用类型。
17+ 由于该类始终表示可重用类型,因此使用不可赋予的类型对类 ` Class ` 进行参数化没有意义。 因此,使用类型参数生成类的两种主要方法(即 ` getClass ` 方法和类
18+ 文本)都被设计为在所有情况下都为类型参数生成可重用类型。
1819
19- 回想一下,编译器专门处理了 ` getClass ` 方法。 一般来说,如果表达式 ` e ` 的类型为 ` T ` ,则表达式 ` e.getClass() ` 的类型为 ` Class<extends | T |> ` ,其中 ` | T | ` 是类型 ` T ` 的删除。 这是一个例子:
20+ 回想一下,编译器专门处理了 ` getClass ` 方法。 一般来说,如果表达式 ` e ` 的类型为 ` T ` ,则表达式 ` e.getClass() ` 的类型为 ` Class<extends | T |> ` ,其
21+ 中 ` | T | ` 是类型 ` T ` 的删除。 这是一个例子:
2022
2123``` java
2224 List<Integer > ints = new ArrayList<Integer > ();
2325 Class<? extends List > k = ints. getClass();
2426 assert k == ArrayList . class;
2527```
2628
27- 这里表达式 ` int ` 具有 ` List<Integer> ` 类型,所以表达式 ` int.getClass() ` 的类型为 ` Class <? extends List> ` ; 这是因为擦除 ` List<Integer> ` 会生成原始类型 ` List ` 。` k ` 的实际值是 ` ArrayList.class ` ,它的类型为 ` Class<ArrayList> ` ,它确实是 ` Class<? extends List> ` 的子类型。
29+ 这里表达式 ` int ` 具有 ` List<Integer> ` 类型,所以表达式 ` int.getClass() ` 的类型为 ` Class <? extends List> ` ; 这是因为擦除 ` List<Integer> ` 会生
30+ 成原始类型 ` List ` 。` k ` 的实际值是 ` ArrayList.class ` ,它的类型为 ` Class<ArrayList> ` ,它确实是 ` Class<? extends List> ` 的子类型。
2831
2932类文字也受到限制; 在类文字中为类型提供类型参数甚至在语法上都是无效的。 因此,以下片段是非法的:
3033
5457
5558解析器在这个短语中遇到了很多麻烦,当它到达文件末尾时仍然感到困惑!
5659
57- 此语法问题导致不规则。 在需要可调整类型的其他位置,您可以提供原始类型(例如 ` List ` )或带有无限制通配符(例如 ` List<?> ` )的参数化类型。 但是,对于类别令牌,您必须提供原始类型; 甚至不会出现无界的通配符。 在前面的代码中用 ` List<?>替换 ` List<Integer >` 会导致类似的错误级联。
60+ 此语法问题导致不规则。 在需要可调整类型的其他位置,您可以提供原始类型(例如 ` List ` )或带有无限制通配符(例如 ` List<?> ` )的参数化类型。 但是,对于类
61+ 别令牌,您必须提供原始类型; 甚至不会出现无界的通配符。 在前面的代码中用 ` List<?> ` 替换 ` List<Integer> ` 会导致类似的错误级联。
5862
5963对类别标记的限制导致一个有用的属性。 无论何处出现类型为 ` Class<T> ` 的类型,类型 ` T ` 都应该是可重用的类型。 对于 ` T[] ` 形式的类型也是如此.
6064
6165《《《 [ 下一节] ( 03_Reflection_for_Primitive_Types.md ) <br />
62- 《《《 [ 返回首页] ( ../README.md )
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-
66+ 《《《 [ 返回首页] ( ../README.md )
Original file line number Diff line number Diff line change 55
66` Java ` 中的每种类型(包括基元类型和数组类型)都具有类文字和相应的类标记。
77
8- 例如,` int.class ` 表示整数的基本类型的类标记(该标记也是静态字段 ` Integer.TYPE ` 的值)。 这个类标记的类型不能是 ` Class<int> ` ,因为 ` int ` 不是一个引用类型,所以它被认为是 ` Class<Integer> ` 。 可以说,这是一个奇怪的选择,因为根据这种类型,您可能期望调用 ` int.class.cast(o) ` 和 ` int.class.newInstance() ` 返回 ` Integer ` 类型的值,但实际上这些调用会引发异常。 同样,你可能会期待这个调用:
8+ 例如,` int.class ` 表示整数的基本类型的类标记(该标记也是静态字段 ` Integer.TYPE ` 的值)。 这个类标记的类型不能是 ` Class<int> ` ,因为 ` int ` 不是一个引
9+ 用类型,所以它被认为是 ` Class<Integer> ` 。 可以说,这是一个奇怪的选择,因为根据这种类型,您可能期望调用 ` int.class.cast(o) ` 和
10+ ` int.class.newInstance() ` 返回 ` Integer ` 类型的值,但实际上这些调用会引发异常。 同样,你可能会期待这个调用:
911
1012``` java
1113 java.lang.reflect. Array . newInstance(int . class,size)
1618另一方面,` int[].class ` 表示具有基本类型 ` integer ` 的组件的数组的类标记,并且此类标记的类型为 ` Class<int[]> ` ,这是允许的,因为 ` int[] ` 是引用类型。
1719
1820《《《 [ 下一节] ( 04_A_Generic_Reflection_Library.md ) <br />
21+
1922《《《 [ 返回首页] ( ../README.md )
Original file line number Diff line number Diff line change 7474一般来说,我们建议如果您需要使用未经检查的强制转换,那么您应该将它们封装到少数库方法中,就像我们在这里所做的那样。 不要让未经检查的代码在您的程序中激增!
7575
7676《《《 [ 下一节] ( 05_Reflection_for_Generics.md ) <br />
77- 《《《 [ 返回首页] ( ../README.md )
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-
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-
137-
138-
139-
77+ 《《《 [ 返回首页] ( ../README.md )
Original file line number Diff line number Diff line change 33
44## 泛型的反思
55
6- 泛型以两种方式改变反射库。 我们已经讨论了反射的泛型,其中 ` Java ` 为类 ` Class<T> ` 添加了一个类型参数。 我们现在讨论泛型的反射,其中 ` Java ` 添加了支持访问泛型类型的方法和类。
6+ 泛型以两种方式改变反射库。 我们已经讨论了反射的泛型,其中 ` Java ` 为类 ` Class<T> ` 添加了一个类型参数。 我们现在讨论泛型的反射,其中 ` Java ` 添加了支
7+ 持访问泛型类型的方法和类。
78
8- 例 ` 7-2 ` 显示了泛型使用反射的简单演示。 它使用反射来查找与给定名称关联的类,并使用反射库类 ` Field ` ,` Constructor ` 和 ` Method ` 打印出与该类关联的字段,构造函数和方法。 两种不同的方法可用于将字段,构造函数或方法转换为用于打印的字符串:旧的 ` toString ` 方法和新的 ` toGenericString ` 方法。 旧方法主要是为了向后兼容性而维护的。 示例 ` 7-3 ` 中显示了一个小样本类,示例 ` 7-4 ` 中显示了使用此类运行的示例。
9+ 例 ` 7-2 ` 显示了泛型使用反射的简单演示。 它使用反射来查找与给定名称关联的类,并使用反射库类 ` Field ` ,` Constructor ` 和 ` Method ` 打印出与该类关联的字
10+ 段,构造函数和方法。 两种不同的方法可用于将字段,构造函数或方法转换为用于打印的字符串:旧的 ` toString ` 方法和新的 ` toGenericString ` 方法。 旧方法
11+ 主要是为了向后兼容性而维护的。 示例 ` 7-3 ` 中显示了一个小样本类,示例 ` 7-4 ` 中显示了使用此类运行的示例。
912
1013例 ` 7-2 ` 。 对泛型的反思
1114
7578 public void Cell.setValue(E)
7679```
7780
78- 示例运行表明,尽管对象和类标记的实体化类型信息不包含有关泛型的信息,但该类的实际字节码确实可以对有关泛型和擦除类型的信息进行编码。 关于泛型类型的信息本质上是一个评论。 运行代码时将被忽略,并且仅保留用于反射。
81+ 示例运行表明,尽管对象和类标记的实体化类型信息不包含有关泛型的信息,但该类的实际字节码确实可以对有关泛型和擦除类型的信息进行编码。 关于泛型类型的信息
82+ 本质上是一个评论。 运行代码时将被忽略,并且仅保留用于反射。
7983
80- 不幸的是,类 `Class` 没有 `toGenericString` 方法,尽管这会很有用。 `Sun` 正在考虑在未来增加这种方法。 同时,所有必要的信息都是可用的,我们将在下一部分解释如何访问它。
84+ 不幸的是,类 `Class` 没有 `toGenericString` 方法,尽管这会很有用。 `Sun` 正在考虑在未来增加这种方法。 同时,所有必要的信息都是可用的,我们将在下一
85+ 部分解释如何访问它。
8186
8287《《《 [下一节](06_Reflecting_Generic_Types.md) <br/>
83- 《《《 [返回首页](../README.md)
88+ 《《《 [返回首页](../README.md)
Original file line number Diff line number Diff line change 3434 implements java.lang.Comparable<E > ,java.io. Serializable
3535```
3636
37- 例 `7-5` 中的代码冗长而直接。 它包含打印类的每个组件的方法:它的超类,它的接口,它的字段和它的方法。 代码的核心是 `printType` 方法,它使用级联的实例测试根据上述五种情况对类型进行分类。
37+ 例 `7-5` 中的代码冗长而直接。 它包含打印类的每个组件的方法:它的超类,它的接口,它的字段和它的方法。 代码的核心是 `printType` 方法,它使用级联的实
38+ 例测试根据上述五种情况对类型进行分类。
3839
39- 例 `7-5`。 如何操作 Type 类型
40+ 例 `7-5`。 如何操作 ` Type ` 类型
4041
4142```java
4243 import java.util.*;
147148如果 ` Type ` 接口有一个 ` toGenericString ` 方法,那么大部分代码都是不必要的。 ` Sun ` 正在考虑这一改变。
148149
149150《《《 [ 下一节] ( ../ch08/00_Effective_Generics.md ) <br />
150- 《《《 [ 返回首页] ( ../README.md )
151+ 《《《 [ 返回首页] ( ../README.md )
You can’t perform that action at this time.
0 commit comments