重载与重写(overload and override)

在java编程中经常会遇到重载和重写,刚接触java的时候对这对概念比较懵比,也不能理解其中的区别,后来在逐渐的学习中更加深刻的理解了其中的原理。哎,说来还是基础知识学的不扎实,这些都是大学期间偷懒欠下的帐。

(一)简单理解

1.重载是在一个类中有多个名称一样的方法,需要根据参数来辨识运行时使用哪个方法。在java中同一个类的同名方法的重载仅依赖(1)参数类型、(2)参数个数、(3)参数顺序三者决定。与返回类型,函数修饰符都无关。

2.重写是多个类继承于同一父类,并同时实现了父类的方法,这时我们在利用父类上转型引用子类并调用接口时,jvm会帮我们执行子类实现的方法逻辑。举个栗子如下:

class Animal{
   public void move(){
      System.out.println("动物可以移动");
   }
}
 
class Dog extends Animal{
   public void move(){
      System.out.println("狗可以跑和走");
   }
}
 
public class TestDog{
   public static void main(String args[]){
      Animal a = new Animal(); // Animal 对象
      Animal b = new Dog(); // Dog 对象
      a.move();// 执行 Animal 类的方法
      b.move();//执行 Dog 类的方法
   }
}

(二)深入理解

java代码在经过javac编译后成为class文件,然后会通过类加载器加载进入内存。加载类文件的过程是由虚拟机外部用户自定义的类装载器实现的,我们常用的就是tomcat,tomcat会将class类文件装载进内存,然后由虚拟机进行验证、准备、解析、初始化等操作。class文件中包含逻辑代码生成的字节码及很多常量池引用组成的元数据。我们在进行方法调用时,实际上目标方法在class文件中就是一个对常量池的符号引用。们需要将这个符号引用转为直接引用,这个过程是jvm在解析过程中实现的。我们的重载和重写就是从解析开始的,接下来我们仔细介绍类的解析及方法的分派过程。

(1)方法调用的解析过程
我们代码中对外部类方法的调用,一开始都是简单的符号引用,虚拟机在类加载阶段会自动帮我们进行对符号引用的解析。这个过程可能在类加载期进行,也可能在运行时进行,主要是为了实现java的动态分派,这个之后说。类加载阶段的解析只能针对类的静态方法、私有方法和final方法进行,因为这些方法在运行期都是不会发生变化的,其他类型的方法可能被子类继承并重写,我们无法在类加载时就确定其直接引用。

(2)方法的分派
方法的分派包含静态分派和动态分派,重载出现在静态分派的过程中,而重写出现在动态分派的过程中。
1.当我们的方法调用在解析过程中找到对应的类后,发现对应的类中有很多同名的方法,这时会根据方法调用时使用的参数类型(称为静态类型)来判定使用哪个函数,然后将依赖类进行加载和初始化,并将符号引用转为这个类方法的内存地址,这个过程就叫做静态分派。
2.当程序运行后,在方法调用的解析过程中发现代码声明的类和运行时引用类不同时,会根据实际引用类的地址去寻找实际引用类的方法列表中寻找是否有相应方法,这个过程叫做动态分派,例如有个Son类继承了父类Father类,并实现了父类的run方法,然后我们执行 Father sonRun = new Son(); sonRun.run();这个过程便是动态分派的过程,动态分派只能在运行期,不能根据静态类型(Father类)确定方法的内存地址,只能在在操作数栈中找到实际类型。

发布了477 篇原创文章 · 获赞 588 · 访问量 267万+

猜你喜欢

转载自blog.csdn.net/qq_15037231/article/details/101114460