欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

方法字节码分析

程序员文章站 2022-04-05 23:45:05
...

下面引用《深入理解Java虚拟机》中关于方法重载的说明

在java语言中,要重载(Overload)一个方法,除了要与原方法具有相同的简单名称之外,还要求必须拥有一个与原方法不同的特征签名,特征签名就是一个方法中各个参数在常量池中的字段符号引用的集合,也就是因为返回值不会包含在特征签名之中,因此Java语言里面无法仅仅依靠返回值的不同来对一个已有方法进行重载。

下面分析方法表示和重载。

1、方法是怎么定义的,以下面这个例子说明方法在字节码中是怎么表示的。

public class Test {
	public void funA(int arg1) {}
	
	public void funA(int arg1, float arg2) {}
	
	public void funB(int arg1) {}
	
	public void funB(float arg1, int arg2) {}
}

上面这个类中定义了3个方法,funA有两个重载方法,它们的参数不一样,同样地,unB也有两个重载方法。注意看2个参数的funA和funB的参数顺序不一样。已经知道字节码中包含一个方法表,它的各式如下:

struct{
    u2 access_flags; // 访问修饰符,如下面的 00 01,表示public
    u2 name_index; // 名称索引,如下面的 00 08,表示引用常量池第8项 funA
    u2 descriptor_index; // 描述符索引,如下面的 00 09,表示引用常量池第9项 (I)V
    u2 attributes_count; // 属性表数量,如下面的 00 01,表示只有一个属性
    attribute_info attributes; // 属性表,只看前两个字节,00 06,表示常量池中第6项 Code
}

下面是字节码的16进制表示的节选部分,因为看起来很奇怪,其他类型还是用javap工具来展示,其中标记出了funA(int args)的方法在字节码中的表示。

方法字节码分析
字节码16进制表示​​​​​

 

 

方法字节码分析
字节码常量池

 

2、重载在Java层面和字节码层面的区别

在java层面中方法的特征签名为 方法名+参数类型+参数顺序。

在字节码层面方法其实可以区别方法的返回类型,描述符中不仅有参数类型和参数顺序,还包含了返回类型。

通过网络上的资料,总结一下Java不使用返回类型作为函数签名主要是因为,降低复杂度,防止方法重载滥用。

参考

《深入理解Java虚拟机:JVM高级特性与最佳实践》

为什么方法返回值不算作方法签名?