前情回顾
上篇博客中我们讲到了class文件的访问标志、类索引、父索引和接口索引集合。本篇博客我们介绍字段表集合。
字段表集合
字段表集合是指由若干个字段表组成的集合。对于在类中定义的若干个字段,经过JVM编译成class文件后,会将相应的字段信息组织到一个叫做字段表集合的结构。
比如:如果一个类中定义了5个字段,JVM在编译该类时会生成5个字段表,并将字段表集合计数器(fileds_count)设为5,5个字段表的信息将依次排列在计数器后。
字段表
字段表用来描述类或是接口中声明的变量,包括类级变量和实例级变量,但不包括方法内部的局部变量。字段表的结构如下图:
我们可以看到字段表的头两个字节是标志位(access_flags),可以表示以下信息:字段的作用域(publc,private,protected),实例变量或类变量(static修饰符),可变性(final),并发可见性(volatile),可否被序列化(transient修饰符),字段数据类型,字段名称。以下是字段访问标志表:
接下来的两个数据项是name_index和descriptor_index。它们分别代表字段的简单名称和字段和方法的描述符(有关简单名称和描述符的见Class文件结构详解(二))。剩下的attributes_count和attributes和属性表集合有关,我们在接下来的章节中讲述。
实例解析:
Comments.class
字段表集合已用蓝色选块标出。
头两个字节时00 04,我们可以得出接下来共有四个字段表,我们将它与字段表和class的常量池对应
Last modified 2019-7-4; size 1166 bytes
MD5 checksum f7b9e128edcf563d8216d36602fda343
Compiled from "Comments.java"
public class com.zust.bean.Comments
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Class #2 // com/zust/bean/Comments
#2 = Utf8 com/zust/bean/Comments
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 comments_no
#6 = Utf8 Ljava/lang/String;
#7 = Utf8 comments_name
#8 = Utf8 comments_context
#9 = Utf8 news_no
#10 = Utf8 <init>
#11 = Utf8 ()V
#12 = Utf8 Code
#13 = Methodref #3.#14 // java/lang/Object."<init>":()V
#14 = NameAndType #10:#11 // "<init>":()V
#15 = Utf8 LineNumberTable
#16 = Utf8 LocalVariableTable
#17 = Utf8 this
#18 = Utf8 Lcom/zust/bean/Comments;
#19 = Utf8 getComments_name
#20 = Utf8 ()Ljava/lang/String;
#21 = Fieldref #1.#22 // com/zust/bean/Comments.comments_name:Ljava/lang/String;
#22 = NameAndType #7:#6 // comments_name:Ljava/lang/String;
#23 = Utf8 setComments_name
#24 = Utf8 (Ljava/lang/String;)V
#25 = Utf8 getComments_context
#26 = Fieldref #1.#27 // com/zust/bean/Comments.comments_context:Ljava/lang/String;
#27 = NameAndType #8:#6 // comments_context:Ljava/lang/String;
#28 = Utf8 setComments_context
#29 = Utf8 getNews_no
#30 = Fieldref #1.#31 // com/zust/bean/Comments.news_no:Ljava/lang/String;
#31 = NameAndType #9:#6 // news_no:Ljava/lang/String;
#32 = Utf8 setNews_no
#33 = Utf8 getComments_no
#34 = Fieldref #1.#35 // com/zust/bean/Comments.comments_no:Ljava/lang/String;
#35 = NameAndType #5:#6 // comments_no:Ljava/lang/String;
#36 = Utf8 setComments_no
#37 = Utf8 SourceFile
#38 = Utf8 Comments.java
可以得出:
00 02 00 05 00 06 00 00 :private comments_no Ljava/lang/String;
00 02 00 07 00 06 00 00 :private comments_name Ljava/lang/String;
00 02 00 08 00 06 00 00 :private comments_context Ljava/lang/String;
00 02 00 09 00 06 00 00 :private news_no Ljava/lang/String;
与Comments.java的源码对比
package com.zust.bean;
public class Comments {
private String comments_no;
private String comments_name;
private String comments_context;
private String news_no;
public String getComments_name() {
return comments_name;
}
public void setComments_name(String comments_name) {
this.comments_name = comments_name;
}
public String getComments_context() {
return comments_context;
}
public void setComments_context(String comments_context) {
this.comments_context = comments_context;
}
public String getNews_no() {
return news_no;
}
public void setNews_no(String news_no) {
this.news_no = news_no;
}
public String getComments_no() {
return comments_no;
}
public void setComments_no(String comments_no) {
this.comments_no = comments_no;
}
}
我们可以发现class文件的字段表集合严谨的按照顺序数量记录了类的字段信息。
其他知识:
1、字段表集合不会列出从父类或接口中继承而来的字段,但会列出内部类指向外部类实例的字段。
2、对字段来说,在java语言层面无法重载,字段名称必须不一致,但对于字节码来说,只要两个字段描述符不同,那 么重名就是合法的,也就是可以实现重载
下文提示:
在本文中我们学习了字段在class文件中的表示方法,下文我们将介绍方法是如何在class文件中组织的。