背景
在日常开发过程中,我们有时候需要查看 文件的内容。如果我们对 文件的结构有基本的了解,那么就会事半功倍。由于这个话题很大,而且我自己的水平也有限,所以每次只写一个很小的主题。本文的主题是理解 文件中字段的 。
要点
- 字段的 体现了字段的类型信息,但是泛型中的类型信息不会记录在其中(例如
List<Integer>中的Integer不会记录在 里) - 字段的 共有三种情况
- 个基本类型
- (除了数组外的)引用类型
- 数组
示例值
基本类型
| 字段在 代码中的类型 | 字段的 |
|---|---|
int | I |
double | D |
long | J |
引用类型
| 字段在 代码中的类型 | 字段的 |
|---|---|
java.lang.Object | Ljava/lang/Object; |
java.lang.Boolean | Ljava/lang/Boolean; |
java.util.List | Ljava/util/List; |
数组
| 字段在 代码中的类型 | 字段的 |
|---|---|
int[] | [I |
java.lang.Boolean[] | [Ljava/lang/Boolean; |
java.lang.Boolean[][] | [[Ljava/lang/Boolean; |
java.lang.Boolean[][][] | [[[Ljava/lang/Boolean; |
正文
示例代码
请将以下代码保存为
import java.util.List;
import java.util.Map;
public class Main {
// base type examples
byte f1;
char f2;
double f3;
float f4;
int f5;
long f6;
short f7;
boolean f8;
// array examples
int[] f9;
double[][] f10;
long[][][][] f11;
// class type examples
Boolean f12;
Long f13;
Object f14;
List<Integer> f15;
Map<String, List<Long>> f16;
List<?> f17;
Void f18;
// more array examples
Boolean[] f19;
Integer[][][] f20;
}
编译
使用以下命令可以编译
javac Main.java
编译之后,执行 tree . 会看到当前目录下多了一个 文件 ⬇️
.
├── Main.class
└── Main.java
1 directory, 2 files
查看 文件的内容
使用以下命令可以查看 文件的详细内容
javap -v -p Main
完整的结果有点长,我把本文关心的部分复制到的下方 ⬇️ (与本文无关的内容用 ... 表示)
...
public class Main
...
{
byte f1;
descriptor: B
flags: (0x0000)
char f2;
descriptor: C
flags: (0x0000)
double f3;
descriptor: D
flags: (0x0000)
float f4;
descriptor: F
flags: (0x0000)
int f5;
descriptor: I
flags: (0x0000)
long f6;
descriptor: J
flags: (0x0000)
short f7;
descriptor: S
flags: (0x0000)
boolean f8;
descriptor: Z
flags: (0x0000)
int[] f9;
descriptor: [I
flags: (0x0000)
double[][] f10;
descriptor: [[D
flags: (0x0000)
long[][][][] f11;
descriptor: [[[[J
flags: (0x0000)
java.lang.Boolean f12;
descriptor: Ljava/lang/Boolean;
flags: (0x0000)
java.lang.Long f13;
descriptor: Ljava/lang/Long;
flags: (0x0000)
java.lang.Object f14;
descriptor: Ljava/lang/Object;
flags: (0x0000)
java.util.List<java.lang.Integer> f15;
descriptor: Ljava/util/List;
flags: (0x0000)
Signature: #40 // Ljava/util/List<Ljava/lang/Integer;>;
java.util.Map<java.lang.String, java.util.List<java.lang.Long>> f16;
descriptor: Ljava/util/Map;
flags: (0x0000)
Signature: #43 // Ljava/util/Map<Ljava/lang/String;Ljava/util/List<Ljava/lang/Long;>;>;
java.util.List<?> f17;
descriptor: Ljava/util/List;
flags: (0x0000)
Signature: #45 // Ljava/util/List<*>;
java.lang.Void f18;
descriptor: Ljava/lang/Void;
flags: (0x0000)
java.lang.Boolean[] f19;
descriptor: [Ljava/lang/Boolean;
flags: (0x0000)
java.lang.Integer[][][] f20;
descriptor: [[[Ljava/lang/Integer;
flags: (0x0000)
public Main();
...
}
...
观察后,会发现 中的 个字段在上面的结果中都出现了。每个字段都有对应的 和 ,有的字段还有 。本文只关心 部分。
理解
The Java® Virtual Machine Specification 中的 4.5. Fields 小节详细介绍了 文件中 的结构,它的开头是这样的 ⬇️
,字面意思是描述符,字段的类型信息保存在其中。在 The Java® Virtual Machine Specification 中的 4.3.2. Field Descriptors 小节 有关于字段的 的描述
从中可以看到
中的内容是 。
中是以下三种内容之一
1. 分类
中一共有 种情况,对应 种基本类型。 4.3.2. Field Descriptors 小节 中提供了如下的表格 (表格的名称是 Table 4.3-A. Interpretation of field descriptors),表格中的 对应 分类下的 种情况
| FieldType term | Type |
|---|---|
B | byte |
C | char |
D | double |
F | float |
I | int |
J | long |
L ClassName ; | Named class or interface type |
S | short |
Z | boolean |
[ ComponentType | Array of given component type |
我们看一下 中属于 分类的字段在 文件中的 ⬇️
2. 分类
分类下,对应的内容由以下三部分组成
L- (其值是对应类的全限定类名,但需要将 替换为 ,细节可以参考 4.2.1. Binary Class and Interface Names 小节)
;
我们来看几个例子 ⬇️
| 全限定类名 | ➡️ | ➡️ L ; |
|---|---|---|
java.lang.Object | java/lang/Object | Ljava/lang/Object; |
java.lang.Boolean | java/lang/Boolean | Ljava/lang/Boolean; |
java.util.List | java/util/List | Ljava/util/List; |
我们看一下 中属于 分类的字段在 文件中的 ⬇️
3. 分类
分类下,对应的内容由以下三部分组成
[- (它的内容是 $\text{FieldType},所以这里出现了递归的情况)
我们来看几个例子 ⬇️
| 代码中的类型 | ➡️ | ➡️ [ |
|---|---|---|
int[] | I | [I |
java.lang.Boolean[] | Ljava/lang/Boolean; | [Ljava/lang/Boolean; |
java.lang.Boolean[][] | [Ljava/lang/Boolean; (这里用到了上一行最后一列的结果) | [[Ljava/lang/Boolean; |
java.lang.Boolean[][][] | [[Ljava/lang/Boolean; (这里用到了上一行最后一列的结果) | [[[Ljava/lang/Boolean; |
我们看一下 中属于 分类的字段在 文件中的 ⬇️
至此,相信您已经了解了 文件中字段的 的格式。