1060 字
5 分钟
Java:继承的构造和代码块
目录
一、子类构造方法
考虑下面的代码:
public class Base { int b; public Base(int b) { this.b = b; System.out.println("Base构造方法运行中。"); }}public class Derived extends Base{ private int a; public Derived(int a) { //需要在第一行加上父类的构造语句,比如:super(1),否则无法运行 //如果参数列表没有b不报错的原因是,子类的构造方法会默认有super(),因此如果参数列表为空编译器会自己构造。 this.a = a; System.out.println("Derived构造方法运行中。"); }}public class Test { public static void main(String[] args) { Derived d = new Derived(1); }
}尝试运行会发现程序会报错。
这是因为子类在运行构造函数之前要先完成父类的构造,也就是说在Derived的构造方法内部,第一行必须是super的构造方法,比如上面的代码第一行就必须是super(1)。
二、代码块执行顺序:
1.回顾
现在我们先回顾一下在一个类的初始化中,代码块的执行顺序。
public class TestDemo { public static String name = "Tim"; public int age; public double weight;
// 实例代码块1 { this.age = 18; this.weight = 60; System.out.println("实例代码块1运行中"); }
// 静态代码块1 static { name = "Timi"; System.out.println("静态代码块1运行中"); }
// 构造方法 public TestDemo(int age, double weight) { System.out.println("构造方法开始执行"); this.age = age; this.weight = weight; System.out.println("构造方法结束执行"); }
// 实例代码块2 { System.out.println("实例代码块2运行中"); }
// 静态代码块2 static { System.out.println("静态代码块2运行中"); }
public void show() { //普通代码块 { System.out.println("普通代码块(局部代码块)运行中"); } System.out.println("姓名:" + name + " 年龄:" + age + " 体重:" + weight); }}2.继承下的代码块运行顺序
在这段代码中,类初始化的时候,代码块的执行顺序是:静态代码块 -> 实例代码块 -> 构造函数。 那么在子类和父类的初始化中,代码块的执行顺序是怎么样的呢?
class Person { public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; System.out.println("Person:构造方法执行"); } { System.out.println("Person:实例代码块执行"); } static { System.out.println("Person:静态代码块执行"); }}class Student extends Person{ public Student(String name,int age) { super(name,age); System.out.println("Student:构造方法执行"); } { System.out.println("Student:实例代码块执行"); } static { System.out.println("Student:静态代码块执行"); }}public class TestDemo { public static void main(String[] args) { Student student1 = new Student("张三",19); System.out.println("==========================="); Student student2 = new Student("李四",20);
}}在如上所示的代码中,结果为:
Person:静态代码块执行Student:静态代码块执行Person:实例代码块执行Person:构造方法执行Student:实例代码块执行Student:构造方法执行===========================Person:实例代码块执行Person:构造方法执行Student:实例代码块执行Student:构造方法执行在这里代码块的运行顺序是:
(父类静态代码块 -> 子类静态代码块) -> 父类的实例和构造 -> 子类的实例和构造。
这样的原因是因为我们知道,静态代码块是在程序加载类的时候就运行了的,并且先有父后有子,因此最早运行的分别是父类和子类的静态代码块。
之后调用构造函数的时候,因为调用子类构造函数的第一步是运行父类的构造函数super,因此,要先运行父类的实例和构造,然后运行子类的实例和构造。
在第二次运行的时候,由于静态代码块只会运行一次,因此只会先后运行父类的实例和构造以及子类的实例和构造。
final关键词
final关键词修饰成员变量的时候,变量视为常量,不能被修改。 修饰类的时候,类不能被继承。 修饰方法的时候,方法不能被重写。
final class Person {
}
class Student extends Person {//final修饰的类不能被继承
}
public class Test { public static void main(String[] args) { final int a = 1; a = 2;//final修饰的成员变量视为常量,不能被更改。 }}下一章讲多态。
部分信息可能已经过时











