前提知识提要

父类与子类

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

继承的特性

子类拥有父类非 private 的属性、方法。
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)
菜鸟教程

代码

class ParentClass {

    static {
        System.out.println("初始化父类静态代码块");
    }

    {
        System.out.println("父类非静态代码块");
    }

    private String name;
    public int value = 1;
    public static int vara = 2;


    /**
     * 父类无参构造方法
     */
    public ParentClass() {
        System.out.println("父类无参构造方法");
        value = 3;
        vara = 4;
    }

    /**
     * 父类有参构造方法
     * @param name
     */
    public ParentClass(String name) {
        this.name = name;
        System.out.println("父类有参构造方法:" + name);
    }

    /**
     * 父类方法
     * @param word
     */
    public void parMethod(String word){
        System.out.println("Method: 父类方法 + " + word);
    }
}

class SubClass extends ParentClass {

    static {
        System.out.println("初始化子类静态代码块");
    }

    {
        System.out.println("子类非静态代码块");
    }

    private String name;
    public int subValue = 5;
    public static int subVara = 6;

    /**
     * 子类无参构造方法
     */
    public SubClass() {
        System.out.println("子类无参构造方法");
        subValue = 7;
        subVara = 8;
    }

    /**
     * 子类有参构造方法
     * @param name
     */
    public SubClass(String name) {
        this.name = name;
        System.out.println("子类有参构造方法:" + name);
    }

    @Override
    public void parMethod(String word){
        System.out.println("Method: 子类重写了父类方法 + " + word);
    }
}

public class InitParentOrChildren {
    public static void main(String[] args) {
        //初始化子类  会先初始化父类
        //初始化父类的时候,会先初始化父类的静态代码块
        //然后再初始化子类的静态代码块
        //接下来才是父类初始化--->子类初始化
//        ParentClass par = new ParentClass("par");
//        par.parMethod("spark");
		SubClass sub1 = new SubClass();
        SubClass sub  = new SubClass("sub");
        sub.parMethod("sub");
        //sub.parMethod("test");
    }
}

第一阶段结论

主方法只初始化了子类,调用的子类的有参构造方法;运行结果如下:

JAVA 子类和父类 注释 java子类与父类的关系_JAVA 子类和父类 注释

首先进行的是 父类的静态代码块初始化,然后再是子类的静态代码块。接下来就是父类和子类的初始化

得出结论
①子类构造器会隐式调用父类的无参构造方法
②子类初始化顺序 :
父类静态代码块–子类静态代码块–父类非静态代码块–父类无参构造方法–子类非静态代码块–子类无参构造方法
父类静态代码块–子类静态代码块–父类非静态代码块–父类无参构造方法–子类非静态代码块–子类有参构造方法

第二阶段结论

将main方法修改一下:

public static void main(String[] args) {
        //初始化子类  会先初始化父类
        //初始化父类的时候,会先初始化父类的静态代码块
        //然后再初始化子类的静态代码块
        //接下来才是父类初始化--->子类初始化
        SubClass sub  = new SubClass("subInit");
        sub.parMethod("sub");
    }

结果如下:

JAVA 子类和父类 注释 java子类与父类的关系_父类_02

得出结论:
子类初始化会初始化父类

第三阶段结论

调整主方法里的代码:

public static void main(String[] args) {
        SubClass sub  = new SubClass("subInit");
        sub.parMethod("sub");
        ParentClass par = new ParentClass("parInit");
        par.parMethod("par");
    }

运行结果:

JAVA 子类和父类 注释 java子类与父类的关系_java_03


得出结论:

静态代码块只初始化一次