思考下面的输出结果
class Father {
int x = 10;
public Father() {
System.out.println("Father " + x);
this.print();
x = 20;
}
public void print() {
System.out.println("Father.x = " + x);
}
}
class Son extends Father {
int x = 30;
public Son() {
System.out.println("Son " + x);
this.print();
x = 40;
}
public void print() {
System.out.println("Son.x = " + x);
}
}
public class ByteCodeInterview1 {
public static void main(String[] args) {
Father f = new Son();
System.out.println(f.x);
}
}
思考片刻
正确输出结果:
Father 10
Son.x = 0
Son 30
Son.x = 30
20
解析
父类和子类的构造方法说明
(1)调用子类的有参或者无参构造方法,如果没有显示的调用父类的某一个构造方法,都会默认先调用父类的空参构造,如果没有会报错。
(2)父类没有空参构造,子类在调用构造方法时,必须在第一行显示的调用父类的有参构造方法。
(3)执行顺序是先执行父类构造方法,在执行子类构造方法。
-
- 所以先会调用父类
Father
无参构造方法
- 所以先会调用父类
public Father() {
this.print();
x = 20;
}
应为 Son
重新了 print
方法,所以 print
使用的是 Son
的 print
。根据类的加载机制 Father
在 初始化阶段 ,而 Son
还没到, Son
的 x的值还是默认 0
所以答应的是
Father 10
Son.x = 0
-
- 在调用子类的构造方法
先来看看 Java 子类 继承 父类 所有属性、方法,主要包括Java 子类 继承 父类 所有属性、方法
从书中看到子类继承父类,子类拥有父类所有的属性和方法,于是使用程序去验证,发现父类的私有属性和私有方法,子类是不能访问的,当然一些父类的私有属性可能可以通过相应的get方法访问到,但是私有的方法似乎不能简单的访问,这里暂不考虑Java反射机制,于是我分析,子类不能继承父类私有的属性及方法,但是分析了内存后,我发现我是错的,在一个子类被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象外部放上子类独有的属性,两者合起来形成一个子类
的对象。所以所谓的继承使子类拥有父类所有的属性和方法其实可以这样理解,子类对象确实拥有父类对象中所有的属性和方法,但是父类对象中的私有属性和方法,子类是无法访问到的,只是拥有,但不能使用。就像有些东西你可能拥有,但是你并不能使用。所以子类对象是绝对大于父类对象的,所谓的子类对象只能继承父类非私有的属性及方法的说法是错误的。可以继承,只是无法访问到而已。
上面 Father.x
并出示和 Son.x
是同一个数据, Son.x
不会覆盖 Father.x
所以子类的构造方法打印的是正确的
Son 30
Son.x = 30
-
- 最后
System.out.println(f.x);
f
现在使用 使用Father
修饰的,是Father
类,所以访问的是Father
的x
属性 打印的也是Father
的 x
- 最后
20