学习笔记之构造方法、静态代码块、构造代码块的执行顺序

学习笔记之构造方法、静态代码块、构造代码块的执行顺序

  • 引言
  • 入门级
    • 测试代码
    • 输出结果
  • 进阶
    • 测试代码
      • Animal.java
      • Cat.java
    • 输出结果
  • 最高难度
    • 测试代码
      • Animal.class
      • Cat.class
    • 输出结果

引言

对于java初学者,各个代码块的执行顺序经常会混淆不清,同时它也是期末考试出题者与面试官十分爱出的考点,很有必要理清它的执行顺序。

入门级

测试代码

public class Cat {
    public Cat() {
        System.out.println("这里是无参构造方法");
    }

    static {
        System.out.println("这里是静态代码块");
    }

    {
        System.out.println("这里是构造代码块2");
    }

    {
        System.out.println("这里是构造代码块1");
    }

    public static void main(String[] args) {
        Cat cat1 = new Cat();
        Cat cat2 = new Cat();
    }
}

输出结果

这里是静态代码块
这里是构造代码块2
这里是构造代码块1
这里是无参构造方法
这里是构造代码块2
这里是构造代码块1
这里是无参构造方法

Process finished with exit code 0

由上述实验,我们可以得出结论:
1)执行顺序:静态代码块>构造代码块>构造方法
2)静态代码块是类被加载的时候就会执行,静态代码块只会被执行一次
3)多个构造代码块存在的时候,构造代码块执行的顺序是根据先后顺序来去执行。

进阶

入门级并无用到继承等技巧,接下来我们谈一谈在有继承关系的情况下,代码块将会怎么样执行。

测试代码

Animal.java

public class Animal {
    private Double weight;
    private Integer age;

    public Animal() {
        System.out.println("这里是Animal的无参构造方法");
    }

    {
        System.out.println("这里是Animal的构造代码块");
    }

    static {
        System.out.println("这里是Animal的静态代码块");
    }
}

Cat.java

public class Cat extends Animal{
    private String type;

    public Cat() {
        System.out.println("这里是Cat的无参构造方法");
    }

    static {
        System.out.println("这里是Cat的静态代码块");
    }

    {
        System.out.println("这里是Cat的构造代码块");
    }

    public static void main(String[] args) {
        Cat cat1 = new Cat();
        Cat cat2 = new Cat();
    }
}

输出结果

这里是Animal的静态代码块
这里是Cat的静态代码块
这里是Animal的构造代码块
这里是Animal的无参构造方法
这里是Cat的构造代码块
这里是Cat的无参构造方法
这里是Animal的构造代码块
这里是Animal的无参构造方法
这里是Cat的构造代码块
这里是Cat的无参构造方法

Process finished with exit code 0

创建了cat1和cat2两个对象,并让Cat类继承了Animal类,代码块执行顺序如下:

父类Animal的静态代码块 -> 子类Cat的静态代码块 -> 父类的构造代码块和构造方法 -> 子类的构造代码块和构造方法。

父类和子类的静态代码块在类初始时都只执行了一次。

最高难度

上面我们已经学会了在继承关系中代码块的执行顺序,接下来我们再来点难的。

测试代码

Animal.class

public class Animal {

    public Animal() {
        System.out.println("这里是Animal的无参构造方法");
    }

    public Animal(String type) {
        System.out.println("这里是animal" + type + "的有参构造方法");
    }

    static {
        System.out.println("这里是Animal的静态代码块");
    }
}

Cat.class

public class Cat extends Animal {

    public Cat(String type) {
        this();
        System.out.println("这里是Cat" + type + "的有参构造方法");
    }

    public Cat() {
        super("猫");
        System.out.println("这里是Cat的无参构造方法");
    }

    static {
        System.out.println("这里是Cat的静态代码块");
    }

    public static void main(String[] args) {
        Cat cat = new Cat("橘猫");
    }
}

输出结果

这里是Animal的静态代码块
这里是Cat的静态代码块
这里是animal猫的有参构造方法
这里是Cat的无参构造方法
这里是Cat橘猫的有参构造方法

Process finished with exit code 0

这边,我们加入了superthis关键字,使之更加复杂。

首先,执行完静态代码块,它会跳入cat的有参构造方法;由于第一行为this(),固调用Cat的无参构造方法;又因为Cat的无参方法第一行为super(“猫”),固调用父类Animal的有参构造方法;然后再依次打印输出。

打印顺序:
父类Animal的有参构造方法 -> 子类Cat的无参构造方法 -> 子类Cat的有参构造方法。

不知道读者看到这边是否已经晕了呢?不妨自己实际编写一遍使用debug进行断点调试会清楚很多哦。

你可能感兴趣的:(java学习)