Java - 代码块

概述

Java 中用 {} 括起来的代码形式叫做代码块。分为 4 种代码块,分别是:

1、普通代码块

定义在 方法中,方法调用时被执行

public static void main(String[] args) {
    {
        System.out.println("普通代码块1");
    }
    System.out.println("main 方法");
    {
        System.out.println("普通代码块2");
    }
}

输出:

普通代码块1
main 方法
普通代码块2

可以看出,普通代码块的执行顺序就是出现在代码中的顺序,一般用于把一种业务相关的代码给括起来,提高代码可读性

2、构造代码块

直接在 类中 定义,创建对象时被调用,每次创建对象都会被调用,并且调用时机优先于构造函数,如果存在多个,执行顺序就是出现的顺序。接下来分别验证这些说法:


验证一

public class CodeBlock {

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

	public CodeBlock1() {
        System.out.println("构造函数");
    }

    public static void main(String[] args) {
        System.out.println("main 方法");
    }

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

上面代码中,只会输出一个 main 方法,因为没有创建对象,所有构造函数和构造代码块都不会执行。


验证二

public class CodeBlock1 {

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

    public CodeBlock1() {
        System.out.println("构造函数");
    }

    public static void main(String[] args) {
        CodeBlock1 codeBlock1 = new CodeBlock1();
        System.out.println("main 方法");
    }

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

输出:

构造代码块1
构造代码块2
构造函数
main 方法

代码块的执行顺序优先于构造函数,并且多个代码块的执行顺序是按照出现在代码中的顺序


验证三

public class CodeBlock1 {

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

    public CodeBlock1() {
        System.out.println("构造函数");
    }

    public static void main(String[] args) {
        CodeBlock1 codeBlock1 = new CodeBlock1();
        System.out.println("main 方法");
        CodeBlock1 codeBlock2 = new CodeBlock1();
    }

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

输出:

构造代码块1
构造代码块2
构造函数
main 方法
构造代码块1
构造代码块2
构造函数

从结果可以看出来,构造代码块的伴随着对象的创建而执行,每一次创建对象都会执行

3、静态代码块

static 关键字进行修饰的代码块,用于初始化类的,为类的属性进行初始化。每个静态代码块只会执行一次,并且是由于 JVM 在加载类的时候就会执行静态代码块,所以静态代码块也会优先于 main 方法 执行。如果类中包含多个静态代码块,执行顺序也是类中出现的顺序。

public class CodeBlock2 {

    private static int i;

    static {
        i = 10;
        System.out.println("静态代码块1");
    }

    public CodeBlock2() {
        System.out.println("构造函数");
    }

    public static void main(String[] args) {
        System.out.println("main 方法");
    }

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

输出:

静态代码块1
静态代码块2
main 方法

可以看到,静态代码块是优先于 main 方法 执行的,而且执行顺序也是类中出现的顺序。


public class CodeBlock2 {

    private static int i;

    static {
        i = 10;
        System.out.println("静态代码块1");
    }

    public CodeBlock2() {
        System.out.println("构造函数");
    }

    public static void main(String[] args) {
        CodeBlock2 codeBlock1 = new CodeBlock2();
        System.out.println("main 方法");
        CodeBlock2 codeBlock2 = new CodeBlock2();
    }

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

输出:

静态代码块1
静态代码块2
构造函数
main 方法
构造函数

从结果可以看到,静态代码块只在类加载的时候执行一次。

注意

  1. 静态代码块不能存在于任何方法体内,因为静态代码块只会在类加载的时候初始化一次
  2. 静态代码块不能直接访问实例的变量和方法,因为静态代码块加载的时候,实例还没有创建

4、同步代码块

使用 synchronized 关键字修饰的代码块,在多线程环境下,对共享数据的读写操作需要进行互斥保护,否则会导致数据不一致。同步代码块需要写在方法中。

public class CodeBlock3 {

    private static final Object object = new Object();

    public static void main(String[] args) {
        System.out.println("main 方法");

        synchronized (object) {

        }
    }
}

总结

public class CodeBlock5 {

    private static int i;

    static {
        i = 10;
        System.out.println("静态代码块,类加载的时候执行");
    }

    {
        System.out.println("构造代码块,优先于构造函数执行");
    }

    public CodeBlock5() {
        System.out.println("构造函数,创建对象的时候执行");
    }

    public static void main(String[] args) {
        CodeBlock5 codeBlock1 = new CodeBlock5();
        codeBlock1.fun1();
        System.out.println("main 方法");
        CodeBlock5.fun2();
    }

    public void fun1() {
    	// 这里的 {} 可以省略
        {
            System.out.println("实例对象的方法,方法被调用时执行");
        }
    }

    public static void fun2() {
        {
            System.out.println("类的方法,方法被调用时执行,晚于静态代码块执行");
        }
    }
}

输出:

静态代码块,类加载的时候执行
构造代码块,优先于构造函数执行
构造函数,创建对象的时候执行
实例对象的方法,方法被调用时执行
main 方法
类的方法,方法被调用时执行,晚于静态代码块执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值