深入理解Java Class文件格式(三)

写在前面

1、类的全限定名

2、描述符

1)、每种类型在描述符中的对应字符串

2)、字段和方法的描述符

​ 3)、特殊方法的方法名

3、总结:


写在前面

        特殊字符串出现在class文件中的常量池中,特殊字符串包括三种: 类的全限定名, 字段和方法的描述符, 特殊方法的方法名。 下面我们就分别介绍这三种特殊字符串。

1、类的全限定名

        在常量池中, 一个类型的名字并不是我们在源文件中看到的那样, 也不是我们在源文件中使用的包名加类名的形式。 源文件中的全限定名和class文件中的全限定名不是相同的概念。

        源文件中的全新定名是包名加类名, 包名的各个部分之间,包名和类名之间, 使用点号分割。 如Object类, 在源文件中的全限定名是java.lang.Object 。

        Class文件中的全限定名是将点号替换成“/” 。 例如Object类在class文件中的全限定名是 java/lang/Object 。  源文件中一个类的名字, 在class文件中是用全限定名表述的。 

2、描述符

1)、每种类型在描述符中的对应字符串

        我们知道在一个类中可以有若干字段和方法, 一个字段或一个方法在class文件中是如何表述的?  方法和字段的描述符并不会把方法和字段的所有信息全都描述出来, 毕竟描述符只是一个简单的字符串。 

        在讲解描述符之前, 要先说明一个问题, 那就是所有的类型在描述符中都有对应的字符或字符串来对应。 比如, 每种基本数据类型都有一个大写字母做对应, void也有一个大写字符做对应。 下表是void和基本数据类型在描述符中的对应。


        基本上都是以类型的首字符变成大写来对应的, 其中long和boolean是特例, long类型在描述符中的对应字符是J, boolean类型在描述符中的对应字符是Z 。 

        基本类型和void在描述符中都有一个大写字符和他们对应, 那么引用类型(类和接口,枚举)在描述符中是如何对应的呢?

        引用类型的对应字符串在描述符中使用一个字符串做对应, 这个字符串的格式是:

 “L” + 类型的全限定名 + “;”

        注意,这三个部分之间没有空格, 是紧密排列的。 如Object在描述符中的对应字符串是: Ljava/lang/Object;  ,ArrayList在描述符中的对应字符串是: Ljava/lang/ArrayList; ,自定义类型com.example.Person在描述符中的对应字符串是: Lcom/example/Person; 。

        我们知道, 在Java语言中数组也是一种类型, 一个数组的元素类型和他的维度决定了他的类型。 比如, 在 int[] a 声明中, 变量a的类型是int[] , 在 int[][] b 声明中, 变量b的类型是int[][] , 在 Object[] c 声明中, 变量c的类型是Object[] 。既然数组是类型, 那么在描述符中, 也应该有数组类型的对应字符串。 在class文件的描述符中, 数组的类型中每个维度都用一个 [ 代表, 数组类型整个类型的对应字符串的格式如下

 若干个“[” + 数组中元素类型的对应字符串

        下面举例: int[]类型的对应字符串是: [I  。 int[][]类型的对应字符串是: [[I 。 Object[]类型的对应字符串是: [Ljava/lang/Object; 。 Object[][][]类型的对应字符串是: [[[Ljava/lang/Object; 。

2)、字段和方法的描述符

         字段的描述符就是字段的类型所对应的字符或字符串。 如: int i 中,字段i的描述符就是 I 。 Object o中,字段o的描述符就是 Ljava/lang/Object; 。double[][] d中,字段d的描述符就是 [[D 。 

        方法的描述符比较复杂, 包括所有参数的类型列表和方法返回值。 它的格式是这样的:

   (参数1类型 参数2类型 参数3类型 ...)返回值类型

其中, 不管是参数的类型还是返回值类型, 都是使用对应字符和对应字符串来表示的, 并且参数列表使用小括号括起来, 并且各个参数类型之间没有空格, 参数列表和返回值类型之间也没有空格。

下面举例说明(此表格来源于《深入Java虚拟机》)

 3)、特殊方法的方法名

        这里的特殊方法是指类的构造方法和类型初始化方法。 构造方法就不用多说了,类型的初始化方法对应到源码中就是静态初始化块。 也就是说, 静态初始化块, 在class文件中是以一个方法表述的, 这个方法同样有方法描述符和方法名。 

        类的构造方法的方法名使用字符串 <init> 表示, 而静态初始化方法的方法名使用字符串 <clinit> 表示。 除了这两种特殊的方法外, 其他普通方法的方法名和源文件中的方法名相同。

3、总结:

        class文件中的特殊字符串包括类(包括接口, 枚举)的全限定名, 字段的描述符和方法的描述符。 其中类的全限定名比较简单易于理解, 字段和方法的描述符由于涉及到每种类型的映射, 可能稍显复杂。 要理解描述符, 主要是要熟记每种类型(包括8种基本数据类型,类类型, 数组类型和void)在描述符中所对应的描述字符或字符串。 

        还有一点需要注意, 就是方法和字段的描述符中, 不包括字段名和方法名, 字段描述符中只包括字段类型, 方法描述符中只包括参数列表和返回值类型。 


原文链接:https://blog.csdn.net/zhangjg_blog/article/details/21487287

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值