反思使程序可以使用物化类型信息。 因此,必要的是,每个类别标记对应于可确定类型。 如果您尝试反映参数化类型,则会获得相应原始类型的指定信息:
List<Integer> ints = new ArrayList<Integer>();
List<String> strs = new ArrayList<String>();
assert ints.get Class() == strs.getClass();
assert ints.getClass() == ArrayList.class;这里整型的类型列表和字符串的类型列表都由同一个类标记表示,其中的类文字被写入 ArrayList.class。
由于该类始终表示可重用类型,因此使用不可赋予的类型对类 Class 进行参数化没有意义。 因此,使用类型参数生成类的两种主要方法(即 getClass 方法和类 文本)都被设计为在所有情况下都为类型参数生成可重用类型。
回想一下,编译器专门处理了 getClass 方法。 一般来说,如果表达式 e 的类型为 T,则表达式 e.getClass() 的类型为 Class<extends | T |>,其 中 | T | 是类型 T 的删除。 这是一个例子:
List<Integer> ints = new ArrayList<Integer>();
Class<? extends List> k = ints.getClass();
assert k == ArrayList.class;这里表达式 int 具有 List<Integer> 类型,所以表达式 int.getClass() 的类型为 Class <? extends List>; 这是因为擦除 List<Integer> 会生 成原始类型 List。k 的实际值是 ArrayList.class,它的类型为 Class<ArrayList>,它确实是 Class<? extends List> 的子类型。
类文字也受到限制; 在类文字中为类型提供类型参数甚至在语法上都是无效的。 因此,以下片段是非法的:
class ClassLiteral {
public Class<?> k = List<Integer>.class; // syntax error
}事实上,Java 的语法使得前面一个短语难以解析,并且可能触发语法错误级联:
% javac ClassLiteral.java
ClassLiteral.java:2: illegal start of expression
public Class<?> k = List<Integer>.class; // syntax error
^
ClassLiteral.java:2: ';' expected
public Class<?> k = List<Integer>.class; // syntax error
^
ClassLiteral.java:2: <identifier> expected
public Class<?> k = List<Integer>.class; // syntax error
^
ClassLiteral.java:4: '}' expected
^
4 errors解析器在这个短语中遇到了很多麻烦,当它到达文件末尾时仍然感到困惑!
此语法问题导致不规则。 在需要可调整类型的其他位置,您可以提供原始类型(例如 List)或带有无限制通配符(例如 List<?>)的参数化类型。 但是,对于类 别令牌,您必须提供原始类型; 甚至不会出现无界的通配符。 在前面的代码中用 List<?> 替换 List<Integer> 会导致类似的错误级联。
对类别标记的限制导致一个有用的属性。 无论何处出现类型为 Class<T> 的类型,类型 T 都应该是可重用的类型。 对于 T[] 形式的类型也是如此.