Skip to content

代码块


基本介绍

(1)代码块又称为初始化块

(2)代码块属于类中的成员(即是类的一部分),类似于方法,将逻辑语句封装在方法体中,通过 { } 包围起来

区别于类方法

(1)无方法名

(2)无参数

(3)无返回类型

(4)只有方法体,而且不用通过对象或类显示调用,加载类或者创建对象时隐式调用

基本使用

1. 修饰符根据需求决定,要写的话,只能写 static

2. 代码块的分类

(1)静态代码块:使用 static 修饰

(2)普通代码块 / 非静态代码块:没有 static 修饰

3. 代码块的内容

可以为任何逻辑语句(输入,输出,方法调用,循环,判断等)

4. 对代码块的理解

相当于另外一种形式的构造器(对构造器的补充),可以做初始化的操作

5. 应用举例

如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的复用性

6. 语法细节:代码块的末尾分号可有可无

⭐ 推荐写法:不写分号

(1)无分号

java
{
  System.out.println("我是末尾没有分号的代码块");
}

(2)有分号

java
{
  System.out.println("我是末尾带有分号的代码块");
};

使用细节

(1)static 代码块也叫静态代码块,它随着类的加载而执行,静态代码块的调用只会执行一次(因为类加载只会执行一次)

注意:静态代码块只能调用类中的静态成员静态方法

(2)普通的代码块,在创建对象实例时,会被隐式调用

只有再创建对象的时候才会调用,创建一次,就会调用一次

如果只是调用类的静态成员时,普通的代码块不会执行

(3)⭐ 类加载时机

1. 使用类的静态成员时(静态属性,静态方法、静态代码块)

2. 创建对象实例时(new)

3. 创建子类实例时,父类也会被加载(子类继承父类,先有父类后有子类)

⭐ 调用顺序问题

创建对象

(1)完成类加载,静态代码静态属性初始化,同时调用

注意:在初始化时,静态代码块和静态属性调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按定义的顺序调用

(2) 调用普通代码块普通属性的初始化,同时调用

注意:在初始化时,普通代码块和普通属性调用的优先级一样,如果有多个普通代码块和多个普通变量初始化,则按定义的顺序调用

(3)构造器的调用(对象层面,不再涉及类相关内容)

⭐ 隐含了super() 的调用

创建子类对象

(1)父类的静态代码块和静态属性(优先级一样,按定义顺序执行)初始化,并调用

(2)子类的静态代码块和静态属性(优先级一样,按定义顺序执行)初始化,并调用

(3) 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行),并调用

(4)父类的构造方法

⭐ 隐含了super() 的调用

(5)子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行),并调用

(6)子类的构造方法

⭐ 隐含了super() 的调用

总结

不涉及继承关系,过程如下

(1)类加载,在方法区加载静态属性、方法信息

(2)静态属性、代码块初始化,并调用

(3)普通属性、代码块初始化,并调用

(4)构造器调用:super()、调用构造器

涉及继承关系,过程如下

(1)类加载,静态相关内容优先完成,先有父类后有子类

(2)非静态内容分别完成,先有父类后有子类

普通属性、代码块初始化,并调用

构造器调用:super()、调用构造器

代码示例

java
public class Test {
    public static void main(String[] args) {
        new b();
    }
}

class a{
    static {
        System.out.println("调用 父类 的 static 代码块");
        System.out.println();
        System.out.println("在 父类 的 static 代码块中调用 静态的 test() 方法");
        test();
        System.out.println("------------------------------------------");
    }

    {
        System.out.println("========类加载完毕,静态相关内容初始化结束,进入 构造器 的初始化!!!========\n");
        System.out.println("------------------------------------------");
        System.out.println("调用 父类 的 普通 代码块");
        System.out.println();
        System.out.println("在 父类 的 普通 代码块中调用 静态的 test() 方法");
        test();
        System.out.println();
        System.out.println("在 父类 的 普通 代码块中调用 静态的 test() 方法");
        test1();
        System.out.println("------------------------------------------");
    }

    public a(){
        System.out.println("调用 父类 的构造器");
        System.out.println("------------------------------------------" + "\n");
        System.out.println("===========该类的所有初始化工作结束,接着完成子类的初始化工作===========\n");
    }

    public static void test(){
        System.out.println("父类中 static 类型的 test() 方法被调用");
    }

    public void test1(){
        System.out.println("父类中 static 类型的 test1() 方法被调用");
    }

}

class b extends a{
    static {
        System.out.println("调用 子类 的 static 代码块");
        System.out.println();
        System.out.println("在 子类 的 static 代码块中调用 静态的 test() 方法");
        test();
        System.out.println("------------------------------------------" + "\n");
    }

    {
        System.out.println("------------------------------------------");
        System.out.println("调用 子类 的 普通 代码块");
        System.out.println();
        System.out.println("在 子类 的 普通 代码块中调用 静态的 test() 方法");
        test();
        System.out.println();
        System.out.println("在 子类 的 普通 代码块中调用 静态的 test1() 方法");
        test1();
        System.out.println("------------------------------------------");
    }

    public b(){
        /*
        隐含的内容
        1. super():默认调用父类的构造器
        2. 调用  本类  的  普通代码块
         */
        System.out.println("调用 子类 的构造器");
        System.out.println("------------------------------------------");
        System.out.println();
        System.out.println("===========子类初始化完成===========\n");
    }

    public static void test(){
        System.out.println("调用 子类 中的 static类型 的 test() 方法");
    }

    @Override
    public void test1(){
        System.out.println("调用 子类 中的 static类型 的 test1() 方法");
    }

}

输出结果

调用 父类 的 static 代码块

在 父类 的 static 代码块中调用 静态的 test() 方法
父类中 static 类型的 test() 方法被调用
------------------------------------------
调用 子类 的 static 代码块

在 子类 的 static 代码块中调用 静态的 test() 方法
调用 子类 中的 static类型 的 test() 方法
------------------------------------------

========类加载完毕,静态相关内容初始化结束,进入 构造器 的初始化!!!========

------------------------------------------
调用 父类 的 普通 代码块

在 父类 的 普通 代码块中调用 静态的 test() 方法
父类中 static 类型的 test() 方法被调用

在 父类 的 普通 代码块中调用 静态的 test() 方法
调用 子类 中的 static类型 的 test1() 方法
------------------------------------------
调用 父类 的构造器
------------------------------------------

===========该类的所有初始化工作结束,接着完成子类的初始化工作===========

------------------------------------------
调用 子类 的 普通 代码块

在 子类 的 普通 代码块中调用 静态的 test() 方法
调用 子类 中的 static类型 的 test() 方法

在 子类 的 普通 代码块中调用 静态的 test1() 方法
调用 子类 中的 static类型 的 test1() 方法
------------------------------------------
调用 子类 的构造器
------------------------------------------

===========子类初始化完成===========


进程已结束,退出代码0