1.Java中类的继承
使用 extends 关键字,比如:经理这个类继承雇员这个类,示例如下:
public class Employee {
String name;
Date hireDate;
Date dateOfBirth;
String jobTitle;
int grade;
…
}
public class Manager extends Employee {
String department;
Employee[] subordinates;
…
}
在这样的定义中,Manager 类被定义,具有 Employee 所拥有的所有变量及方法。所有这些变量和方法都是从父类的定义中继承来的。所有的程序员需要做的是定义额外特征或规定将适用的变化。
注意:这种方法是在维护和可靠性方面的一个伟大进步。如果Employee 类中进行修改,那么,Manager 类就会自动修改,而不需要程序员做任何工作,除了对它进行编译
2.类的初始化
在 Java 编程语言中,对象的初始化是非常结构化的,这样做是为了保证安全。在前面
的模块中,看到了当一个特定对象被创建时发生了什么。由于继承性,对象被完成,而且下
述行为按顺序发生:
(1)存储空间被分配并初始化到 0 值
(2)进行显式初始化
(3)调用构造方法
(4)层次中的每个类都会发生最后两个步骤,是从最上层开始。Java 技术安全模式要
求在子类执行任何东西之前,描述父类的一个对象的各个方面都必须初始化。因此,Java
编程语言总是在执行子构造方法前调用父类构造方法的版本。
有继承的类在运行的时候,一定要记得:初始化子类必先初始化父类,这是 Java 程序
的一个基本运行过程。比如:
上述类的基本运行顺序是:
(1):先运行到第 7 行,这是程序的入口
(2):然后运行到第 8 行,这里要 new 一个 Test,就要调用 Test 的构造方法
(3):就运行到第 4 行,注意:初始化子类必先初始化父类
(4):要先初始化父类,所以运行到第 14 行
(5):然后是第 13 行,初始化一个类,必须先初始化它的属性
(6):然后是第 15 行
(7):然后是第 16 行,表示父类初始化完成
(8):然后是回到子类,开始初始化属性,因此运行到第 2 行,然后是第 3 行
(9):子类属性初始化完过后,才回到子类的构造方法,执行里面的代码,也就是第 5 行
(10):然后是第 6 行,表示 new 一个 Test 实例完成
(11):然后回到 main 方法中执行第 9 行
(12):然后是第 10 行
运行结果是:
现在初始化父类
Java 私塾的年龄是 1000 年
3.super 关键字的功能:
(1):点取父类中被子类隐藏了的数据成员
(2):点取已经覆盖了的方法
(3):作为方法名表示父类构造方法
例如:
public class Employee {
private String name;
private int salary;
public String getDetails() {
return "Name: " + name + "\nSalary: " + salary;
}
}
public class Manager extends Employee {
private String department;
public String getDetails() {
return super.getDetails() + // 调用父类的方法
"\nDepartment: " + department;
}
}
在许多情况下,使用默认构造方法来对父类对象进行初始化。
当然也可以使用 super 来显示调用父类的构造方法。
public class Employee {
String name;
public Employee(String n) {
name = n;
}
}
public class Manager extends Employee {
String department;
public Manager(String s, String d) {
super(s);
department = d;
}
}
PS:父类没有构造函数或者是无参数的构造函数,子类构造时会调用父类的构造函数,如果有参数的话要显示调用,并写在子类构造函数的第一行。
注意:无论是 super 还是 this,都必须放在构造方法的第一行。
通常要定义一个带参数的构造方法,并要使用这些参数来控制一个对象的父类部分的构
造。可能通过从子类构造方法的第一行调用关键字 super 的手段调用一个特殊的父类构造方
法作为子类初始化的一部分。要控制具体的构造方法的调用,必须给 super()提供合适的参
数。当不调用带参数的 super 时,缺省的父类构造方法(即,带 0 个参数的构造方法)被隐
含地调用。在这种情况下,如果没有缺省的父类构造方法,将导致编译错误。
public class Employee {
String name;
public Employee(String n) {
name = n;
}
}
public class Manager extends Employee {
String department;
public Manager(String s, String d) {
super(s); // 调用父类参数为 String 类型的构造方法
department = d;
}
}
当被使用时,super 或 this 必须被放在构造方法的第一行。显然,两者不能被放在一
个单独行中,但这种情况事实上不是一个问题。如果写一个构造方法,它既没有调用
super(…)也没有调用 this(…),编译器自动插入一个调用到父类构造方法中,而不带参数。
其它构造方法也能调用 super(…)或 this(…),调用一个 static 方法和构造方法的数据链。
最终发生的是父类构造方法(可能几个)将在链中的任何子类构造方法前执行。