字段表(field_info)用于描述接口或者类中剩余的变量。字段(field)包括类级变量以及实例级变量,但不包括在方法内部剩余的局部变量。我们可以想一想在Java中描述一个字段可以包含什么信息?可以包括的信息有:字段的作用域(public,private,protected修饰符)、是实例变量还是类变量(static修饰符)、可变性(final)、并发可见性(volatile修饰符,是否强制从主内存读写)、可否被序列化(transient修饰符)、字段数据类型(基本类型、对象、数组),字段名称。上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫什么名字、字段被定义为什么数据类型、这些都是无法固定的,只能引用常量池中的常量来描述。表6-8中列出了字段表的最终格式。

JAVA rs 字段名 java中的字段指什么_JAVA rs 字段名

    字段修饰符放在access_flags项目中,它与类中的access_flags项目是非常类似的,都是一个u2的数据类型,其中可以设置的标志位和含义见表6-9。

JAVA rs 字段名 java中的字段指什么_字段_02

    很明显,在实际情况中,ACC_PUBLIC、ACC_PRIVATE、ACC_PROTECTED三个标志最多只能选择其一,ACC_FINAL、ACC_VOLATILE不能同时选择。接口之中的字段必须有ACC_PUBLIC、ACC_STATIC、ACC_FINAL标志,这些都是由Java本身的语言规则所决定的。

    跟随access_flag标志的是两项索引值:name_index和descriptor_index。它们都是对常量池的作用,分别代表着字段的简单名称以及字段和方法的描述符。现在需要解释一下“简单名称”、“描述符”以及前面出现过多次的“全限定名”这三种特殊字符串的概念。

   全限定名和简单名称很好理解,以代码清单6-1中的代码为例,“org/fenixsoft/clazz/TestClass”是这个类的全限定名,仅仅是把类全名中的“.”替换成了“/”而已,为了使连续的逗哥全限定名之间不产生混淆,在使用时最后一般会加入一个“;”表示全限定名结束。简单名称是指没有类型和参数修饰的方法或者字段名称,这个类中的inc()和m字段的简单名称分别是“inc”和“m”。

   相对于全限定名和简单名称来说,方法和字段的描述符就要复杂一些。描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值根据描述符规则,基本数据类型(byte、char、double、float、int、short、boolean)以及代表无返回值的void类型都用一个大写字符来表示,而对象类型则用字符L加对象的全限定名来表示,详见表6-10.

JAVA rs 字段名 java中的字段指什么_JAVA rs 字段名_03

    对于素组类型,每一维度将使用一个前置的“[”字符来描述,如一个定义为“java.lang.String[][]”类型的二位数组,将被记录为:“”“”“[[Ljava/lang/String;”,一个整数数组“int[]”将被记录为“[I”。

   用描述符来描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号“()”之内。如方法void inc()的描述符为“()V”,方法 java.lang.String.toString()的描述符为"()Ljava/lang/String;",方法int indexOf(char[]source,int sourceOffset,int sourceCount,char[]target,int targetOffset,int targetCount,int formIndex)的描述符为“([CII[CIII)I”。

字段表集合中不会列出从超类或者父接口中继承而来的字段,但有可能列出原本Java代码之中不存在的字段,碧如在内部类中为了保持对外部类的访问性,会自动添加指向外部类实例的字段。另外在Java语言中字段是无法重载的,两个字段的数据类型、修饰符不管是否相同,都必须使用不一样的名称,但是对于字节码来讲,如果两个字段的描述不一致,那字段重名就是合法的。