|
| 1 | +## 反射类型是可维持类型 |
| 2 | + |
| 3 | +反思使程序可以使用物化类型信息。 因此,必要的是,每个类别标记对应于可确定类型。 如果您尝试反映参数化类型,则会获得相应原始类型的指定信息: |
| 4 | + |
| 5 | +```java |
| 6 | + List<Integer> ints = new ArrayList<Integer>(); |
| 7 | + List<String> strs = new ArrayList<String>(); |
| 8 | + assert ints.get Class() == strs.getClass(); |
| 9 | + assert ints.getClass() == ArrayList.class; |
| 10 | +``` |
| 11 | + |
| 12 | +这里整型的类型列表和字符串的类型列表都由同一个类标记表示,其中的类文字被写入 `ArrayList.class`。 |
| 13 | + |
| 14 | +由于该类始终表示可重用类型,因此使用不可赋予的类型对类 `Class` 进行参数化没有意义。 因此,使用类型参数生成类的两种主要方法(即 `getClass` 方法和类文本)都被设计为在所有情况下都为类型参数生成可重用类型。 |
| 15 | + |
| 16 | +回想一下,编译器专门处理了 `getClass` 方法。 一般来说,如果表达式 `e` 的类型为 `T`,则表达式 `e.getClass()` 的类型为 `Class<extends | T |>`,其中 `| T |` 是类型 `T` 的删除。 这是一个例子: |
| 17 | + |
| 18 | +```java |
| 19 | + List<Integer> ints = new ArrayList<Integer>(); |
| 20 | + Class<? extends List> k = ints.getClass(); |
| 21 | + assert k == ArrayList.class; |
| 22 | +``` |
| 23 | + |
| 24 | +这里表达式 `int` 具有 `List<Integer>` 类型,所以表达式 `int.getClass()` 的类型为 `Class <? extends List>`; 这是因为擦除 `List<Integer>` 会生成原始类型 `List`。`k` 的实际值是 `ArrayList.class`,它的类型为 `Class<ArrayList>`,它确实是 `Class<? extends List>` 的子类型。 |
| 25 | + |
| 26 | +类文字也受到限制; 在类文字中为类型提供类型参数甚至在语法上都是无效的。 因此,以下片段是非法的: |
| 27 | + |
| 28 | +```java |
| 29 | + class ClassLiteral { |
| 30 | + public Class<?> k = List<Integer>.class; // syntax error |
| 31 | + } |
| 32 | +``` |
| 33 | + |
| 34 | +事实上,`Java` 的语法使得前面一个短语难以解析,并且可能触发语法错误级联: |
| 35 | + |
| 36 | +```java |
| 37 | + % javac ClassLiteral.java |
| 38 | + ClassLiteral.java:2: illegal start of expression |
| 39 | + public Class<?> k = List<Integer>.class; // syntax error |
| 40 | + ^ |
| 41 | + ClassLiteral.java:2: ';' expected |
| 42 | + public Class<?> k = List<Integer>.class; // syntax error |
| 43 | + ^ |
| 44 | + ClassLiteral.java:2: <identifier> expected |
| 45 | + public Class<?> k = List<Integer>.class; // syntax error |
| 46 | + ^ |
| 47 | + ClassLiteral.java:4: '}' expected |
| 48 | + ^ |
| 49 | + 4 errors |
| 50 | +``` |
| 51 | + |
| 52 | +解析器在这个短语中遇到了很多麻烦,当它到达文件末尾时仍然感到困惑! |
| 53 | + |
| 54 | +此语法问题导致不规则。 在需要可调整类型的其他位置,您可以提供原始类型(例如 `List`)或带有无限制通配符(例如 `List<?>`)的参数化类型。 但是,对于类别令牌,您必须提供原始类型; 甚至不会出现无界的通配符。 在前面的代码中用 `List<?>替换 `List<Integer>` 会导致类似的错误级联。 |
| 55 | + |
| 56 | +对类别标记的限制导致一个有用的属性。 无论何处出现类型为 `Class<T>` 的类型,类型 `T` 都应该是可重用的类型。 对于 `T[]` 形式的类型也是如此. |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | + |
| 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 | + |
0 commit comments