今天看了一道面试题。
Java类初始化顺序
这种基础知识,在大学学过,校招时在牛客网恶补过,最终不过一忘,所以还是来记录一下。
先上一种没有继承关系的类。
代码:
package test;
public class Father {
public static String staticField = printStaticField();
public String field = printField();
static {
System.out.println("【静态代码块】");
}
{
System.out.println("【非静态代码块】");
}
public static String printStaticField() {
System.out.println("【静态变量】");
return "静态变量";
}
public String printField() {
System.out.println("【非静态变量】");
return "非静态变量";
}
public Father() {
System.out.println("【构造方法代码块】");
}
public static void main(String[] args) {
new Father();
}
}
输出:
【静态变量】
【静态代码块】
【非静态变量】
【非静态代码块】
【构造方法代码块】
这时候有个问题:静态变量和静态代码块的先后顺序呢?非静态变量和非静态代码块的先后顺序呢?
答:经测试,就是代码写的先后顺序。
再来一种有继承关系的类。
代码(父类):
package test;
public class Father {
public static String staticField = printStaticField();
public String field = printField();
static {
System.out.println("【父类-静态代码块】");
}
{
System.out.println("【父类-非静态代码块】");
}
public static String printStaticField() {
System.out.println("【父类-静态变量】");
return "父类-静态变量";
}
public String printField() {
System.out.println("【父类-非静态变量】");
return "父类-非静态变量";
}
public Father() {
System.out.println("【父类-构造方法代码块】");
show();
}
public void show() {
System.out.println("【父类-普通方法】");
}
}
代码(子类):
package test;
public class Son extends Father {
public static String staticField = printStaticField();
public String field = printField();
static {
System.out.println("【子类-静态代码块】");
}
{
System.out.println("【子类-非静态代码块】");
}
public static String printStaticField() {
System.out.println("【子类-静态变量】");
return "子类-静态变量";
}
public String printField() {
System.out.println("【子类-非静态变量】");
return "子类-非静态变量";
}
public Son() {
System.out.println("【子类-构造方法代码块】");
show();
}
public void show() {
System.out.println("【子类-普通方法】");
}
public static void main(String[] args) {
new Son();
}
}
输出(换行是我人为换行,为了方便观察):
【父类-静态变量】
【父类-静态代码块】
【子类-静态变量】
【子类-静态代码块】
【子类-非静态变量】//这里出现 子类 的原因是:子类方法被父类方法 覆盖
【父类-非静态代码块】
【父类-构造方法代码块】
【子类-普通方法】//这里出现 子类 的原因是:子类方法被父类方法 覆盖
【子类-非静态变量】
【子类-非静态代码块】
【子类-构造方法代码块】
【子类-普通方法】
在这里增加一个继承关系里的方法覆盖知识点。
如果不想让父类方法被覆盖,那么可以用 在父类方法上加 final 关键字,但是加了关键字之后,子类中根本不允许存在和父类方法名相同的方法(方法参数一致的情况)。 那么还可以用 private 关键字,嗯,可以实现了。