跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java 代码块详解:控制流、方法、实例、静态及同步代码块

Java 中的五种代码块:控制流语句代码块、方法代码块、实例初始化代码块、静态代码块和同步代码块。阐述了各类代码块的定义、语法特征、作用域及使用场景。重点讲解了实例代码块与构造方法的区别,静态代码块与构造方法的区别,以及它们在类加载和对象创建过程中的执行顺序。通过代码示例展示了同步代码块在多线程环境下的应用,并通过练习题巩固了静态变量与局部变量的概念。

心动瞬间发布于 2026/3/29更新于 2026/10/26116 浏览
Java 代码块详解:控制流、方法、实例、静态及同步代码块

1. 什么是代码块?

在学习各种语言的时候,有些语句需要使用 {} 将代码围起来,有些语句确不用,但是总体来说所有的代码被包围在一个 {} 中,这是为什么呢?

答:想一想我们学数学时的复杂运算,是不是有很多的括号?如:(), [], {}。有了这些括号就使得运算有条理。

换言之,大括号 {} 用于明确地定义代码块的开始和结束,使得代码的组织结构更加清晰。这有助于阅读和理解代码,尤其是在复杂的程序中,代码块可能嵌套在其他代码块内部。

学习 Java 编程语言时,理解代码块的概念是非常重要的。代码块是 Java 中的基本组成部分之一,它允许你将一组语句组织在一起,以便可以作为一个单元进行处理。

代码块的定义
代码块是一组用大括号 {} 包围的语句。在 Java 中,代码块可以出现在多个地方,比如在方法内部、循环结构中、条件语句中等。

代码块的类型

  1. 控制流语句代码块:定义在控制流语句中(如 if、else、for、while、do-while、switch 等)中,用于指定在特定条件下或循环迭代中应该执行的代码。
  2. 方法代码块:定义在方法内部的代码块,通常用于执行特定的任务。
  3. 实例初始化代码块:没有 static 关键字的代码块,用于初始化实例变量。
  4. 静态代码块:用 static 关键字标记的代码块,通常用于初始化类变量。
  5. 同步代码块:使用 synchronized 关键字,用于多线程编程中的同步操作。

代码块的作用域
代码块中定义的变量只能在该代码块内部被访问,这称为局部变量。局部变量的作用域仅限于定义它们的代码块。

2. 控制流代码块

2.1 定义

控制流语句代码块是普通代码块的一种特殊应用,它们出现在控制流语句(如 if、else、for、while、do-while、switch 等)中,用于指定在特定条件下或循环迭代中应该执行的代码。这些代码块没有特殊的关键字修饰,它们仅仅是由大括号 {} 包围的一组语句。

2.2 示例

switch 语句中的代码块

int month = 4;
switch (month) {
    case 1:
    case 2:
    case 3:
        // 这是一个代码块,用于处理 1 月、2 月和 3 月
        System.out.println("第一季度");
        break;
    case 4:
    case 5:
    case 6:
        
        System.out.println();
        ;
    
    :
        
        System.out.println();
}
// 另一个代码块,用于处理 4 月、5 月和 6 月
"第二季度"
break
// 可以有更多的 case 和代码块
default
// 默认情况下的代码块
"其他季度"

while 循环代码块

int count = 0;
while (count < 3) {
    // 这是一个代码块,用于循环直到 count 等于 3
    System.out.println("计数:" + count);
    count++;
}

for 循环中的代码块

// 使用 for 循环打印 1 到 5 的数字
for (int i = 1; i <= 5; i++) {
    // 这是一个代码块,用于每次循环迭代
    System.out.println(i);
}

if-else 语句中的代码块

int score = 85;
if (score >= 90) {
    // 这是一个代码块,用于处理分数大于等于 90 的情况
    System.out.println("优秀");
} else {
    // 另一个代码块,用于处理分数小于 90 的情况
    System.out.println("良好");
}

3. 方法代码块

3.1 定义

方法代码块是方法体的具体实现,它定义了方法的行为。方法代码块以一对大括号 {} 开始和结束,位于方法声明之后。

方法代码块的主要作用是实现方法的逻辑。它包含了方法执行时需要执行的所有操作,比如变量声明、条件判断、循环、数据计算等。

3.2 示例及说明

public class ControlFlowInMethod {
    public static void main(String[] args) {
        // 调用方法并传递参数
        printMultiplesOfTen(5);
    }

    // 方法声明,用于打印 10 的倍数
    public static void printMultiplesOfTen(int count) {
        // 方法代码块开始
        for (int i = 1; i <= count; i++) {
            // 控制流语句的代码块
            if (i % 2 == 0) {
                // 检查是否为偶数
                System.out.println("10 * " + i + " = " + (10 * i));
            }
        }
        // 方法代码块结束
    }
}

在这个例子中,printMultiplesOfTen 方法用于打印 10 的倍数。

方法代码块中包含了一个 for 循环,这是一个 控制流语句的代码块。在 for 循环内部,还有一个 if 语句,它 也是一个控制流语句的代码块,用于检查当前的迭代次数 i 是否为偶数,如果是偶数,则打印出 10 乘以当前迭代次数的结果。

当 main 方法被调用时,它会调用 printMultiplesOfTen 方法,并传递一个参数 5,这意味着方法会打印出 10 的 1 倍到 5 倍的偶数倍数。

4. 实例代码块(构造代码块)

4.1 定义

实例初始化代码块(Instance Initializer Block),也简称为实例代码块,是在类体内部、方法外部定义的代码块,它不属于任何方法。实例初始化代码块主要用于初始化类的实例变量,可以看作是对象创建时的初始化设置。

它没有访问修饰符、返回类型、名称或参数列表,只有一对大括号 {} 包含的代码。

实例初始化代码块在对象被创建时执行,且在任何构造方法执行之前执行。如果有多个构造方法,实例初始化代码块在每个构造方法之前都会执行。

4.2 示例及说明

public class Example {
    int number;
    String name;

    // 实例初始化代码块
    {
        number = 10;
        // 初始化实例变量 number
        name = "初始化数据";
        // 初始化实例变量 name
        System.out.println("实例代码块已经运行");
    }

    // 构造方法
    public Example() {
        System.out.println("构造函数已经被运行");
        System.out.println("--------------------------------");
        System.out.println("Constructor is called.");
    }

    public static void main(String[] args) {
        Example obj = new Example();
        System.out.println("Number: " + obj.number + ", Name: " + obj.name);
    }
}

在这个例子中,实例初始化代码块在对象 obj 被创建时执行,它初始化了 number 和 name 两个实例变量,并且会打印出被使用的消息。随后,当构造方法 Example() 被调用时,它会打印出构造方法被调用的信息。最后,在 main 方法中,我们可以看到对象的实例变量已经被初始化。

执行结果示例

4.3 实例代码块与构造方法的区别

虽然 构造方法 和 实例代码块 都可以用于初始化对象,但它们之间存在一些区别:

  1. 构造方法可以被重载(即一个类可以有多个构造方法),而实例代码块只能有一个。
  2. 构造方法可以访问参数并使用 this 关键字调用其他构造方法,而实例代码块不能。
  3. 实例代码块在任何构造方法执行之前执行,而构造方法在对象创建时执行。

5. 静态代码块

5.1 定义

静态代码块(Static Initializer Block),也称为静态初始化块,是 Java 类中的一个特殊代码块,它使用 static 关键字声明。静态代码块主要用于初始化类的静态变量或执行只需要执行一次的操作。

静态代码块定义在类的成员变量声明之后、方法定义之前。它使用 static 关键字标记,并且没有访问修饰符、返回类型、名称或参数列表,只有一对大括号 {} 包含的代码。

静态代码块在类被 Java 虚拟机(JVM)加载时执行,且仅执行一次。这意味着静态代码块的执行与类的任何对象的创建无关,它只与类的加载有关。

5.2 示例及说明

public class Example {
    static int staticNumber;
    static String staticName;

    // 静态代码块
    static {
        staticNumber = 10;
        // 初始化静态变量 staticNumber
        staticName = "初始化数据";
        // 初始化静态变量 staticName
        System.out.println("Static block is executed.");
    }

    public static void main(String[] args) {
        System.out.println("Static number: " + staticNumber);
        System.out.println("Static name: " + staticName);
    }
}

在这个例子中,静态代码块在 Example 类被加载时执行,它初始化了两个静态变量 staticNumber 和 staticName,并打印了一条消息。当 main 方法被调用时,它打印出这两个静态变量的值。

执行结果示例

5.3 静态代码块与构造方法的区别

静态代码块与构造方法的主要区别在于:

  1. 静态代码块用于初始化静态变量,而构造方法用于初始化实例变量。
  2. 静态代码块在类加载时执行,而构造方法在对象创建时执行。
  3. 静态代码块中的代码不能访问类的实例变量或调用实例方法,因为这些实例成员依赖于具体的对象实例。

5.4 使用场景

静态代码块适用于以下场景:

  1. 初始化静态常量。
  2. 执行只需要执行一次的资源密集型操作,如加载配置文件、连接数据库等。
  3. 在类加载时执行一些必要的初始化操作,这些操作与任何对象的创建无关。

6. 同步代码块

6.1 定义

同步代码块(Synchronized Block)是 Java 中用于实现线程同步的一种机制。它允许多个线程在访问共享资源时,保证同一时间只有一个线程可以执行特定的代码段,从而避免发生线程安全问题,如数据不一致、竞态条件等。

同步代码块可以通过 synchronized 关键字来定义。它可以出现在任何方法中,或者作为一个独立的代码块出现在方法内部。当使用 synchronized 关键字时,你需要指定一个锁对象(lock object),代码块内的代码只有在获得该对象的锁之后才能执行。

同步代码块的主要作用是确保在多线程环境中,当一个线程访问同步代码块时,其他线程将被阻塞,直到锁被释放。这样可以防止多个线程同时修改同一个资源,确保数据的一致性和线程安全。

6.2 示例及说明

public class Example {
    private static final Object lock = new Object();

    public void methodOne() {
        synchronized (lock) {
            // 同步代码块
            System.out.println("Method One is executing.");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Method One finished.");
        }
    }

    public void methodTwo() {
        synchronized (lock) {
            // 同步代码块
            System.out.println("Method Two is executing.");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Method Two finished.");
        }
    }

    public static void main(String[] args) {
        final Example example = new Example();
        Thread threadOne = new Thread(() -> example.methodOne());
        Thread threadTwo = new Thread(() -> example.methodTwo());
        threadOne.start();
        threadTwo.start();
    }
}

在这个例子中,methodOne 和 methodTwo 都包含了一个同步代码块,它们使用相同的锁对象 lock。当 main 方法启动两个线程时,它们将尝试执行这两个方法。由于同步代码块使用了相同的锁对象,所以这两个方法不会同时执行,从而避免了线程安全问题。

6.3 同步代码块与同步方法的区别

同步代码块与同步方法的主要区别在于:

  1. 同步方法使用 synchronized 关键字修饰整个方法,而同步代码块只同步方法中的特定部分。
  2. 同步代码块允许更细粒度的控制,你可以只同步需要同步的部分,而不是整个方法。

同步代码块适用于以下场景:

  1. 当只需要同步方法中的一小部分代码时。
  2. 当多个方法需要同步同一个资源,但不是整个方法时。
  3. 当需要提高性能,减少不必要的同步开销时。

7. 实例代码块(构造代码块)、静态代码块和构造函数的运行顺序

7.1 在同一个类中

public class Example {
    // 静态代码块
    static {
        System.out.println("静态代码块已经运行");
    }

    // 实例初始化代码块
    {
        System.out.println("实例代码块已经运行");
    }

    // 构造方法
    public Example() {
        System.out.println("构造函数已经被运行");
    }

    public static void main(String[] args) {
        Example obj = new Example();
    }
}

运行结果:

执行结果示例

有同学疑问,运行顺序是不是和代码块写的顺序有关呢?

那打乱顺序再次运行:

public class Example {
    // 构造方法
    public Example() {
        System.out.println("构造函数已经被运行");
    }

    // 实例初始化代码块
    {
        System.out.println("实例代码块已经运行");
    }

    // 静态代码块
    static {
        System.out.println("静态代码块已经运行");
    }

    public static void main(String[] args) {
        Example obj = new Example();
    }
}

执行结果示例

显然,代码块运行的顺序和代码块的位置无关,先运行静态代码块,再运行实例代码块,最后运行构造函数。

7.2 在继承关系中

同学们思考一下将会打印出什么呢?

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() {
        // super();
        System.out.println("子类的构造函数");
    }

    public static void main(String[] args) {
        Son son = new Son();
    }
}

运行结果

执行结果示例

下面的代码又会打印出什么呢?是不是上面的内容打印两边呢?

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() {
        // super();
        System.out.println("子类的构造函数");
    }

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

打印结果:

执行结果示例

8. 练习题

下面的代码运行后会发生什么?

public class Test {
    public int aMethod() {
        static int i = 0;
        i++;
        return i;
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.aMethod();
        int j = test.aMethod();
        System.out.println(j);
    }
}

执行结果示例

答:D 解析:局部代码块中不能有静态变量。只有成员变量才能是静态变量。

下列代码运行后会输出什么?

public class Test {
    static int cnt = 6;
    static {
        cnt += 9;
    }

    public static void main(String[] args) {
        System.out.println("cnt = " + cnt);
    }

    static {
        cnt /= 3;
    }
}

执行结果示例

答案:A 解析: (1)静态变量初始化:static int cnt = 6; 在类加载时进行初始化,因此 cnt 的初始值为 6。 (2)第一个静态代码块先被执行。在第一个静态代码块中,cnt 的值被增加了 9,即:cnt = 6 + 9 = 15。 (3)紧接着,第二个静态代码块执行,此时 cnt = 15。在第二个静态代码块中,cnt 的值被除以 3,即:cnt = 15 / 3 = 5。

目录

  1. 1. 什么是代码块?
  2. 2. 控制流代码块
  3. 2.1 定义
  4. 2.2 示例
  5. 3. 方法代码块
  6. 3.1 定义
  7. 3.2 示例及说明
  8. 4. 实例代码块(构造代码块)
  9. 4.1 定义
  10. 4.2 示例及说明
  11. 4.3 实例代码块与构造方法的区别
  12. 5. 静态代码块
  13. 5.1 定义
  14. 5.2 示例及说明
  15. 5.3 静态代码块与构造方法的区别
  16. 5.4 使用场景
  17. 6. 同步代码块
  18. 6.1 定义
  19. 6.2 示例及说明
  20. 6.3 同步代码块与同步方法的区别
  21. 7. 实例代码块(构造代码块)、静态代码块和构造函数的运行顺序
  22. 7.1 在同一个类中
  23. 7.2 在继承关系中
  24. 8. 练习题

更多推荐文章

查看全部
  • 基于 Python Flask 与 Vue 的电影院在线售票系统设计
  • VS Code C++ 非标准库头文件编译错误解决方案
  • 拆解 Garry Tan 的 gstack 架构逻辑:构建 AI 工程化约束框架
  • Linux LVM 磁盘管理工具详解:物理卷、卷组与逻辑卷操作
  • AI 生成代码缺陷分类与缓解策略综述
  • Java IO 核心:BufferedReader、BufferedWriter、PrintStream 与 PrintWriter 详解
  • 比萨中文离线地图应用上线
  • 禁用 VS 2022 中 Copilot 的自动代码补全
  • AIGC 从创意到创造:概念、场景与进阶
  • 基于改进 YOLOv11n 的无人机红外目标检测算法
  • SOFATracer 分布式链路追踪组件剖析
  • 2026 年 9 款主流 AI Agent 框架横评:OpenClaw 及衍生版对比与场景推荐
  • C++ 笔试刷题实战:打怪、字符串分类及城市群问题解析
  • Visual Studio 禁用 GitHub Copilot 代码提示的操作指南
  • 商汤开源 SenseNova-MARS 模型:实现多模态搜索推理新突破
  • 飞算 JavaAI 智能编程助手功能介绍
  • 前端开发常用开源 JavaScript 库、框架与工具
  • 人形机器人:百万亿美元赛道的终极逻辑与通用平台化
  • PyCharm 与 GitHub Copilot 配置指南:学生认证流程详解
  • 算法实战:位运算解法详解(两数之和、唯一数字、消失数字)

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online