最近在忙着找工作,之前也参加了阿里巴巴的校园招聘笔试,里面最后第二道题就是关于Java中构造函数、静态变量和静态语句块的加载问题。于是,小弟就自己就着Java的子类父类构造函数和静态语句块问题,去实践操作了一下,分享出来给大家看看。
一、Java的子类父类构造函数问题
首先来看例子:
-
public class Child extends Father{ public Child(String s){ System.out.println("子类有参数"); } public Child(){ System.out.println("子类无参数"); } // static{ // System.out.println("子类静态块"); // } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Child child = new Child("child_one"); } } class Father{ public Father(){ System.out.println("父类无参数"); } public Father(String s){ System.out.println("父类有参数"); } // static{ // System.out.println("父类静态块"); // } }
运行结果:
父类无参数
子类有参数
说明:在main方法中使用子类Child的含参构造函数去创建对象,而同时调用了父类Father的无参构造函数,并没有去调用含参的构造函数。
情况1:那如果把父类Father中的无参构造函数注释掉,为了表现说服力,把子类Child的无参构造函数也注释掉,此时就会报错了:
Problem:未定义隐式超构造函数 Father()。必须显式调用另一个构造函数
这也说明了之前提到的运行结果。
情况2:如果只想加载父类Father的含参构造函数,而不是无参构造函数,该怎么办?此时,super就发挥作用了,将子类Child的含参构造函数修改为:
public Child(String s){
super(s); //必须第一行
System.out.println("子类有参数");
}
再运行,运行结果为:
父类有参数
子类有参数
顺便说一句,类自身的构造函数之间互相调用,使用this关键字。
二、Java静态语句块和构造函数的加载顺序
其实这方面不需要细说,因为静态部分是随着类的加载而加载,构造函数是随着对象的创建而加载。也就是说,若在main方法中只声明子类Child类型的变量,静态部分会被执行,当然不会存在构造函数这一说了。接下来只是想通过子类Child继承父类Father的情况来展示静态块和构造函数的加载顺序。
将文章开始的代码中的静态语句块部分消除注释,运行结果为:
父类静态块
子类静态块
父类无参数
子类有参数
也就是说不管是父类还是子类的静态部分,都会在构造函数之前执行,它们是随着类的加载而加载。而父类肯定是先于子类加载,就像肯定先有猿,才有人一样。