来看这样一段代码,试问它的输出是什么??
abstract class Person{
public Person(){ //2
this.print(); //3
}
public abstract void print(); //3
}
class Student extends Person{
private int num = 100;
public Student(int num){ // 1
this.num = num;
}
public void print(){ //4
System.out.println(this.num); //5
}
}
public class Day8{
public static void main(String[] args){
new Student(30); // 1
}
}
分析:
Person类是一个抽象类,这里来复习一下抽象类的概念:
1.抽象类拥有0 ~ N 个抽象方法 ,而含有抽象方法的类必须为抽象类
2.抽象类必须有子类(所以abstract 与 final 不能同时出现)(因为final定义的类不能拥有子类,所以矛盾了)
3.若抽象类的子类不是抽象类,则这个子类必须覆写抽象类的所有抽象方法;(所以abstract与private不能同时出现)
4.抽象类可以使用子类向上转型为其实例化。抽象类一定不能直接实例化对象(无论是否有抽象方法)
以上介绍了抽象类的相关规定,接下来来看这道例题;
1. 首先执行main方法中的 1;即来到了Student类的构造方法
2. Student类是Person类的子类,所以实例化子类时,先执行父类构造方法,在执行子类构造方法;⭐
3. 所以此时来到父类构造方法2,接下来来到3;
4. 由于父类中的3是一个抽象方法,它在子类中有一个方法覆写,所以会调用子类的方法覆写;
5. 此时来到了4,然后执行5
6. 5中的this.num是子类中的num,此时整个流程还在处于调用父类构造方法中,而num的初始化是在子类构造方法中完成⭐,所以num此时还未被初始化;
7. 所以输出0;
结果:
PS E:\JAVASE\ClassExercise> javac -encoding UTF-8 Day8.java
PS E:\JAVASE\ClassExercise> java Day8
0
我们可以将这段代码进行编译时的代码还原(将隐藏代码显示出来)
abstract class Person{
public Person(){ //2
this.print(); //3
}
public abstract void print(); //3
}
class Student extends Person{
public Student(int num){ // 1
super();
int num = 100;
this.num = num;
}
public void print(){ //4
System.out.println(this.num); //5
}
}
public class Day8{
public static void main(String[] args){
new Student(30); // 1
}
}
可以看到num的初始化在Student类的构造方法中;
这个代码是模拟的,助于理解,真正编译在那块是会报错的哦?!!!