Java基础系列(十四):方法调用

方法签名

方法的签名包括两部分,方法名和参数列表。

如果在子类中定义了一个与父类签名相同的方法,那么子类中的这个方法就会覆盖父类中这个相同签名的方法。这里需要注意一点,在覆盖一个方法的时候,子类方法不能低于父类方法的可见性,比如一个同样方法签名的方法在父类中的修饰符是public,而在子类中是private

但是需要注意的是,返回类型并不是方法签名的一部分,所以,在覆盖方法的时候,一定要保证返回类型的兼容性,允许子类将覆盖方法的返回类型定义为原返回类型的子类型。

方法调用流程

假设,这里有一个类A,其中有方法f,当这个类A创建一个实例a并调用f时,a.f(args)时有一些细节需要注意:

  1. 首先,编译器查看对象的声明类型和方法名。这里需要注意一点,有可能存在多个名字为f,但是参数类型不一样的方法。例如,可能存在方法f(int)和方法f(String)。编译器将会一一列举所有C类中名为f的方法和其父类中访问属性为public且名为f的方法(需要注意的是,父类的私有方法不可访问)。
  1. 第二步,编译器将会查看调用方法时提供的参数类型。如果在所有名为f的方法中存在一个与提供的参数类型完全匹配,就会选择这个方法。这个过程被称为重载解析。例如,对于调用a.f("Hello")来说,编译器将会挑选f(String),而不是f(int)。如果编译器没有找到与参数类型匹配的方法,或者发现经过类型转换后有多个方法与之匹配,编译器就会报错。
  1. 如果是private方法,static方法,final方法或者构造器,那么编译器将可以准确的知道调用哪个方法,我们将在这种方式称为静态绑定,而与之对应的是之前我们提过的调用的方法依赖于隐式参数的实际类型,并且在运行的时候实现动态绑定。
  1. 每次调用方法都要进行搜索,时间和资源的开销相当大。所以,虚拟机预先为每个类创建了一个方法表,其中列出了所有方法的签名和实际调用的方法。这样一来,在真正调用方法的时候,虚拟机仅仅去查找这个表就可以了。

方法解析流程

  1. 虚拟机提取对象变量所对应类的方法表,该方法表在编译过程中产生。
  2. 虚拟机会搜索定义调用该方法签名的类,这时,虚拟机已经知道该调用哪个方法。
  3. 虚拟机调用并方法。

原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知


公众号

你可能感兴趣的:(Java基础系列(十四):方法调用)