理解Java的方法调用

116 阅读2分钟
  1. 编译器先查看对象的声明类型和方法名,如果有名称相同,但是参数不同的方法(重载),编译器会一一列举该对象中所有同名的方法和它的超类中的同名且可访问的方法,超类的私有方法不可以访问。
  2. 接下来编译器确定方法调用中提供的参数类型。编译器如果找到一个与搜提供参数类型完全匹配的方法,就选择这个方法,由于类型转换,会涉及到一些复杂的情况。编译器如果找不到与参数类型匹配的方法,或者发现经过类型转换后发现有多个方法与之匹配,编译器就会报错。
  • 方法的签名:方法的名字和参数列表称为方法的签名,如果在子类中定义了一个与超类签名相同的方法,那么子类中的这个方法就会覆盖超类中这个相同签名的方法。
  1. 如果是private方法、static方法、final方法或者构造器,编译器准确知道应该应该调用哪个方法,这称为动态绑定。如果调用的方法依赖于隐式参数的实际类型,那么必须在运行时使用动态绑定。
  • 隐式参数:隐式参数表示在方法中使用,但是没有写在方法参数中也没有在方法体内声明的变量(在类中声明的变量),例如:下面代码中的name和salary两个变量就是隐式参数。
public Employee(String n, double s) {
	super();
	this.name = n;
	this.salary = s;
}
  1. 程序在使用动态绑定调用方法时,虚拟机必须调用与x所引用对象对应的实际类型对应的那个方法。举个例子:假设x的实际类型是D,它是C的子类,如果D定义了f方法,就使用D类中的f方法,如果没有,就在C中查找f,以此类推。
  • 每次调用这个方法都要完成这样的搜索,开销很大,所以虚拟机预先为每一个类计算一个方法表,其中列出所有方法的签名和要调用的实际方法。这个方法可能是当前类的方法,也可能是它的超类的方法。如果调用的是super.f(param),编译器将搜索隐式参数超类的方法表。