前言

复习下Java中的静态代码块、构造代码块、构造函数、普通代码块

正文

概念介绍

1、静态代码块

定义:在类中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。

注意点

  • 静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数。如果一个类中有多个静态代码块,会按照书写顺序依次执行。
  • 静态代码块不能存在任何方法体中。因为非静态普通方法是通过加载类,然后new出实例化对象,通过对象才能调用这个方法,而静态代码块只需要加载类之后就能运行了。而对于静态方法,在类加载的时候,静态方法也已经加载了,但是我们必须要通过类名或者对象名才能访问,也就是说静态代码块是主动运行的,而静态方法是被动运行的。
  • 静态代码块不能直接访问实例变量和实例方法

2、构造代码块

定义:直接在类中定义且没有加static关键字的代码块称为构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。如果存在多个构造代码块,执行顺序由他们在代码中出现的次序决定,先出现先执行。

3、普通代码块

普通代码块和构造代码块的区别是,构造代码块是在类中定义的,而普通代码块是在方法体中定义的。且普通代码块的执行顺序和书写顺序一致。

4、构造函数

注意点

  • 构造函数的命名必须和类名完全相同。在java中普通函数可以和构造函数同名,但是必须带有返回值;
  • 构造函数的功能主要用于在类的对象创建时定义初始化的状态。它没有返回值,也不能用void来修饰。
  • 构造函数不能被直接调用,必须通过new运算符在创建对象时才会自动调用;而一般的方法是在程序执行到它的时候被调用的;
  • 当定义一个类的时候,通常情况下都会显示该类的构造函数,并在函数中指定初始化的工作也可省略,不过Java编译器会提供一个默认的构造函数,此默认构造函数是不带参数的。

实例测试

CodeBlock类代码如下:

/**
 * Copyright (C), 2015-2020
 * FileName: CodeBlock
 * Author:   niko
 * Date:     2020/6/23 11:08
 * Description: 测试各种代码块
 * History:
 * <author>          <time>          <version>
 * 逝不等琴生          11:08           1.0
 */
package com.nzc.codeblock;

public class CodeBlock {
    static {
        System.out.println("我是静态代码块——静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数");
    }

    {
        System.out.println("我是构造代码块——优先于构造函数执行,每次创建一个对象都执行一次");
    }

    public CodeBlock() {
        System.out.println("我是构造函数——每创建一个对象就执行一次");
    }

    public void normalFunction() {
        System.out.println("我是非静态方法中的代码块——被类对象调用时执行");
    }

    public static void staticFunction() {
        System.out.println("我是静态方法中的代码块——被类调用时执行");
    }
}

测试类代码如下:

/**
 * Copyright (C), 2015-2020
 * FileName: TestCodeBlock
 * Author:   niko
 * Date:     2020/6/23 11:14
 * Description:
 * History:
 * <author>          <time>          <version>
 * 逝不等琴生          11:14           1.0
 */
package com.nzc.test;

import com.nzc.codeblock.CodeBlock;

public class TestCodeBlock {
    public static void main(String[] args) {
        new CodeBlock().normalFunction();
        new CodeBlock().normalFunction();
        System.out.println("=============以下为静态方法调用==========");
        CodeBlock.staticFunction();
        CodeBlock.staticFunction();
    }
    //    测试结果:
//我是静态代码块——静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数
//我是构造代码块——优先于构造函数执行,每次创建一个对象都执行一次
//我是构造函数——每创建一个对象就执行一次
//我是非静态方法中的代码块——被类对象调用时执行
//我是构造代码块——优先于构造函数执行,每次创建一个对象都执行一次
//我是构造函数——每创建一个对象就执行一次
//我是非静态方法中的代码块——被类对象调用时执行
//=============以下为静态方法调用==========
//我是静态方法中的代码块——被类调用时执行
//我是静态方法中的代码块——被类调用时执行
}

测试结果如下图所示:

总结:

即执行顺序: 静态代码块>构造代码块>构造函数>普通代码块

父类和子类中代码块执行顺序

实例如下:

父类

public class Father {
    static {
        System.out.println("我是父类静态代码块");
    }

    {
        System.out.println("我是父类构造代码块");
    }

    public Father() {
        System.out.println("我是父类构造函数");
    }

}

子类

public class Son extends Father {
    static {
        System.out.println("我是子类静态代码块");
    }

    {
        System.out.println("我是子类构造代码块");
    }

    public Son() {
        System.out.println("我是子类构造函数");
    }

}

测试类如下


public class Test {
    public static void main(String[] args) {
        Son son1 = new Son();
        System.out.println("===================");
        Son son2 = new Son();
    }

}

测试截图:

总结:

静态代码块内容先执行,随后执行父类构造代码块和构造方法,接着执行子类构造代码块和构造方法。