【Java 试题】从一道题目再看 Java 继承
一 题目
一道 Java 基础题:两个类,ClassB 继承自 ClassA,代码如下,判断输出内容:
ClassA:
ClassB:
如上代码所示,判断 ClassB 的输出内容及输出顺序。
二 分析
2.1 关键信息
题目中的关键要素:继承、代码块、静态代码块、toString()方法重写。
我们先看 ClassB,main 方法中,通过 System.out.println() 打印 ClassB 的实例内容。这里我们可以比较容易分析出是先 new ClassB(), 然后在输出前隐式调用了 ClassB 的 toString()方法。ClassB 继承自 ClassA,但因为重写了 toString(),所以 toString()方法会输出 F;
new ClassB()的动作在前,并且 ClassB 有两个代码块,一个非静态(构造)代码块,一个静态代码块;初步猜测执行顺序是先静态代码块,后构造代码块。只看 ClassB,那么输出顺序应该是 D E F。接下来 ClassA 中的代码块,是否会输出,以及会怎样输出?
2.2 代码块
2.2.1 代码块类型
我们先回顾 Java 代码块的基本概念和四种类型:
2.2.1.1 普通代码块
在方法或语句中出现的{}就称为普通代码块。普通代码块和一般语句的执行顺序由他们在代码中出现的次序决定,先出现先执行。
2.2.1.2 构造代码块
直接在类中定义且没有加 static 关键字的代码块称为{}构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。如果存在多个构造代码块,执行顺序由他们在代码中出现的次序决定,先出现先执行。
2.2.1.3 静态代码块
在 java 中使用 static 关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于 JVM 在加载类时会执行静态代码块,所以静态代码块先于主方法执行。如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。
注意:
1.静态代码块不能存在于任何方法体内。
2.静态代码块不能直接访问实例变量和实例方法,需要通过类的实例对象来访问。
2.2.1.4 同步代码块
使用 synchronized(){}包裹起来的代码块,在多线程环境下,对共享数据的读写操作是需要互斥进行的,否则会导致数据的不一致性。同步代码块需要写在方法中。
2.2.2 静态代码块和构造代码块的异同点
相同点:都是 JVM 加载类后且在构造函数执行之前执行,在类中可定义多个,一般在代码块中对一些 static 变量进行赋值。
不同点:静态代码块在非静态代码块之前执行。静态代码块只在第一次 new 时执行一次,之后不在执行。而非静态代码块每 new 一次就执行一次。
2.3 继承
2.3.1 定义
从 2.2.1 和 2.2.2 的内容,可以验证我们对 ClassB 部分的输出猜测。下一步,继承。ClassB 继承自 ClassA,回顾继承定义:
继承使用的 extends 关键字,子类会继承父类的所有成员变量和方法。当我们创建一个类的时候,无时无刻不在继承,如果我们没有明确的指出继承哪个类,隐式的继承 Object 类。
Java 使用 super 关键字来调用父类的构造方法。在子类继承父类的时候,会自动调用父类的构造函数,如果都是无参的构造函数,则不需要显示调用,如果是有参的构造函数,子类继承的时候就需要显示的用 super 调用。
2.3.2 再次分析
基于 2.3.1 的概念理解,我们再回到题目。new ClassB()时,因为在 ClassB 内没有编写构造方法,所以实际上会调用 ClassA 的构造方法,这时也会执行 ClassA 中的静态代码块和普通代码块。换个角度理解,ClassB 继承自 ClassA,继承的是非 private 属性和方法,那么也包含代码块,只不过静态代码块只在第一次 new 时调用一次,普通代码块每次 new 时调用一次。
那么,根据上述内容,ClassB 在创建实例时,执行顺序就是:
1、ClassA 的静态代码块,打印 “A”;
2、ClassB 的静态代码块,打印 “D”(静态代码块部分);
3、ClassA 的普通代码块,打印“B”;
4、ClassB 的普通代码块,打印“E”(至此构造过程结束);
5、toString()方法,打印“F”。
执行 ClassB 的 main 方法,查看控制台输出:
由此确认打印顺序推测无误。
三 总结
老实说,遇到这样的题目,开始有些不知所措,因为太过基础,基础到以前没有想过去验证。但如果对相关基础概念有比较深的理解的话,还是可以推测出来的。借此机会,再夯实以下,也不算是坏事。
版权声明: 本文为 InfoQ 作者【程序员架构进阶】的原创文章。
原文链接:【http://xie.infoq.cn/article/8cb8b86bb9ac711949be80878】。文章转载请联系作者。
评论