新数据结构(4)——Java继承
基本概念
继承的本质:重复使用已经定义好的方法和域,实现代码的重复利用。
使用继承之后,创建的子类可以方便地调用父类中已经定义的方法。
一个继承的例子:
重载和重写
重载
重载:发生在同一个类里,指的是方法名相同但是参数列表(包括参数类型、数量或顺序)不同。
重载的一个例子:
public void run(){
}
public void run(String nane){
}
public void run(int age){
}
重写
重写(或覆盖):子类重写父类的方法,指的是子类中的方法与父类中的方法具有相同的方法名和参数列表(包括参数类型和数量)。
重写的一个例子:
重写后,如果声明一个父类类型的变量并指向一个父类的实例,那么将使用父类原本的方法(如下图)。在这种情况下,即使存在子类对父类方法的重写,由于实际指向的是父类对象,因此调用的仍然是父类的方法。在内存中,如果仅创建了父类对象而没有创建子类对象,那么即使子类重写了父类的方法,这些重写的方法也不会被调用,因为内存中只有父类对象的实例存在。
重写后,如果声明一个子类类型的变量指向一个子类的实例,并通过这个变量调用被重写的方法,那么将使用子类重写的方法(如下图)。在这种情况下,由于实际指向的是子类对象或者声明的就是子类类型,因此调用的将是子类中重写后的方法。
重写后,如果声明一个父类类型的变量指向一个子类的实例,并通过这个变量调用被重写的方法,那么将使用子类重写的方法(如下图)。在这种情况下,由于实际指向的是子类对象或者声明的就是子类类型,因此调用的将是子类中重写后的方法。
加载顺序
在Java程序的执行过程中,静态类(或包含静态成员和静态初始化块的类)会在类加载阶段最先被加载到内存中。这个加载过程发生在程序执行之前,确保静态成员被初始化,并且静态初始化块中的代码在类第一次被引用时执行。
首先调用父类(如上图和下图)
如下图,当Java程序运行时,如果创建了子类对象,JVM(Java虚拟机)会在内存中为子类对象分配空间。由于子类继承了父类,JVM也会确保父类的相关信息(如父类的字段和方法)在需要时被加载到内存中。但是,这并不意味着“父类对象”被“创建”了;实际上,只有子类对象被创建,而父类的信息是以一种特殊的方式(如通过类加载器)被访问和利用的。
从内存角度看方法重写
重写后,当通过子类对象调用被重写的方法时,子类将调用其自己提供的重写方法,而不是继承自父类的原始方法。
上图代码在内存里的体现
当声明一个父类类型的引用变量并让它指向一个父类对象时,通过该引用变量调用方法会调用父类原本的方法,因为此时内存中只有父类对象的实例,没有子类对象的实例存在。
上图的内存图
super关键字
super
关键字可以在子类中用来显式地调用父类的方法或构造器。当在子类中重写父类的方法时,可以使用 super
关键字来调用被重写的父类方法,以保持对父类行为的访问。同样地,在子类的构造器中,可以使用 super
关键字来调用父类的构造器,以确保父类被正确初始化。
调用父类的方法
调用父类的构造器(必须在子类构造方法里调用)
综合应用(判断执行顺序)
类加载:
-当Java虚拟机(JVM)启动并运行一个Java程序时,它会加载程序中用到的所有类。在这个例子中,Demo
类和Test
类都会被加载。
-类加载是Java虚拟机将类的描述信息从类文件(.class文件)加载到内存,并对类数据进行校验、转换和初始化等过程。
静态代码块的执行:
-在类加载的过程中,JVM会执行类中的静态代码块。静态代码块在类加载时执行,且只执行一次。
-在Demo
类中,有两个静态代码块(尽管第二个静态代码块由于语法错误11e
和重复的static{
而不会被正确执行),但第一个静态代码块System.out.println("11");
会被执行。
-同时,在静态代码块中还有一个静态变量的初始化public static Demo demo=new Demo("+++");
。这个静态变量的初始化也会导致Demo
类的构造器被调用,并打印出"===+++"
。
main
方法的执行:
-当类加载和静态代码块执行完毕后,JVM会开始执行main
方法,这是Java程序的入口点。
-在Test
类的main
方法中,创建了一个新的Demo
对象Demo demo=new Demo("---");
。这会导致Demo
类的构造器再次被调用,并打印出"===---"
。