java泛型数组字段的descriptor仅含擦除后类型,完整泛型信息通过signature属性保存;如t[]对应descriptor为[ljava/lang/object;而signature为[tt;,list[]对应descriptor为[ljava/util/list;、signature为[ljava/util/list;。

Java中泛型数组在Class文件的field_info结构里,不会直接出现在descriptor_index中,而是通过额外的Signature属性来保留其完整泛型信息。
泛型数组字段的 descriptor 与 signature 区别
Java字段的类型描述符(descriptor_index)受类型擦除限制,只能表示运行时实际类型。例如:
-
private List<string>[] data;</string>→descriptor是[Ljava/util/List; -
private T[] items;(其中T extends Number)→descriptor是[Ljava/lang/Object;
而Signature属性则记录擦除前的完整泛型签名,用于反射、注解处理、序列化等场景还原类型语义。
Signature 属性在 field_info 中的位置和结构
每个含泛型的字段,若其声明包含类型参数(如 T[]、List extends Comparable<t>>[]</t>),编译器会在该字段的attributes列表中插入一个Signature属性:
-
attribute_name_index指向常量池中字符串"Signature" -
attribute_length固定为2 -
signature_index指向常量池中一个CONSTANT_Utf8_info,其内容是符合JVM规范的泛型签名字符串
泛型数组签名的语法格式
签名字符串遵循JVM泛型签名语法,数组用[前缀,泛型类型用尖括号嵌套。关键规则:
- 原始类型数组:
[I(int[])、[Ljava/lang/String;(String[]) - 参数化类型数组:
[Ljava/util/List<ljava>;</ljava> - 带界泛型类型数组:
[TT;(对应T[]),其中T必须在类签名或方法签名中已声明;若T extends Number,则签名中会先定义T:Ljava/lang/Number;,字段签名才可引用[TT; - 通配符数组:
[Ljava/util/List>;(对应List extends Comparable super T>>[])
实际例子:编译后字段签名对照
源码:
class Container<t extends charsequence> {
private T[] elements;
private List<integer>[] buckets;
}</integer></t>
对应字段签名(UTF-8字符串):
-
elements字段:[TT;(注意:此处T需依赖类签名中的类型变量定义) -
buckets字段:[Ljava/util/List<ljava>;</ljava>
这些签名被存入常量池,并由字段的Signature属性索引指向,确保运行时可通过Field.getGenericType()正确还原。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











