【Java 学习】详讲代码块:控制流语句代码块、方法代码块、实例代码块(构造代码块)、静态代码块、同步代码块

💬 欢迎讨论:如对文章内容有疑问或见解,欢迎在评论区留言,我需要您的帮助!

👍 点赞、收藏与分享:如果这篇文章对您有所帮助,请不吝点赞、收藏或分享,谢谢您的支持!

🚀 传播技术之美:期待您将这篇文章推荐给更多对需要学习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 示例

  1. if-else 语句中的代码块

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

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

    int count = 0;while (count < 3) {// 这是一个代码块,用于循环直到count等于3System.out.println("计数: " + count);count++;
    }
    
  4. 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:// 另一个代码块,用于处理4月、5月和6月System.out.println("第二季度");break;// 可以有更多的case和代码块default:// 默认情况下的代码块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; // 初始化实例变量numbername = "Code哈哈笑"; // 初始化实例变量nameSystem.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被创建时执行,它初始化了numbername两个实例变量,并且会打印出被使用的消息。随后,当构造方法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; // 初始化静态变量staticNumberstaticName = "Code哈哈笑"; // 初始化静态变量staticNameSystem.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类被加载时执行,它初始化了两个静态变量staticNumberstaticName,并打印了一条消息。当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();}
}

在这个例子中,methodOnemethodTwo都包含了一个同步代码块,它们使用相同的锁对象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. 练习题

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

    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。

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

    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
    解析:局部代码块中不能有静态变量。只有成员变量才能是静态变量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/65852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【亚马逊云科技】基于Amazon EKS部署高可用的OceanBase的最佳实践

一、前言 随着企业业务的快速发展和数据量的不断增长&#xff0c;高性能、高可用的数据库解决方案成为了关键需求。OceanBase作为一款分布式关系型数据库&#xff0c;以其高扩展性、高可用性和高性能的特点&#xff0c;逐渐受到企业的广泛关注。然而&#xff0c;在复杂的分布式…

【工具】—— SpringBoot3.x整合swagger

Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务的接口文档。Swagger简单说就是可以帮助生成接口说明文档&#xff0c;操作比较简单添加注解说明&#xff0c;可以自动生成格式化的文档。 项目环境 jdk17SpringBoot 3.4.0Sp…

从0入门自主空中机器人-2-1【无人机硬件框架】

关于本课程&#xff1a; 本次课程是一套面向对自主空中机器人感兴趣的学生、爱好者、相关从业人员的免费课程&#xff0c;包含了从硬件组装、机载电脑环境设置、代码部署、实机实验等全套详细流程&#xff0c;带你从0开始&#xff0c;组装属于自己的自主无人机&#xff0c;并让…

基于视觉语言模型(VLM)的CogAgent

前言 CogAgent 是由清华大学与智谱AI联合推出的一个多模态大模型&#xff0c;专注于图形用户界面&#xff08;GUI&#xff09;的理解和导航。它代表了在视觉语言模型&#xff08;VLM&#xff09;领域的一项重要进展&#xff0c;特别是在GUI Agent能力方面。相较于传统的基于文…

win10、win11-鼠标右键还原、暂停更新

系统优化 win 10jihuo win 11jihuo鼠标右键还原暂停更新 update 2024.12.28win 10 jihuo winx&#xff0c;打开powershell管理员&#xff0c;输入以下命令,选择1并等待 irm https://get.activated.win | iex参考&#xff1a;https://www.bilibili.com/video/BV1TN411M72J/?sp…

C# 找出给定三角形的所有角度(Find all angles of a given triangle)

给定三角形在二维平面上所有三个顶点的坐标&#xff0c;任务是找到所有三个角度。 示例&#xff1a; 输入&#xff1a;A (0, 0), B (0, 1), C (1, 0) 输出&#xff1a;90, 45, 45 为了解决这个问题&#xff0c;我们使用下面的余弦定律。 c^2 a^2 …

【数据结构】(Python)差分数组。差分数组与树状数组结合

差分数组&#xff1a; 基于原数组构造的辅助数组。用于区间修改、单点查询。区间修改的时间复杂度O(1)。单点查询的时间复杂度O(n)。差分数组的元素&#xff1a;第一个元素等于原数组第一个元素&#xff0c;从第二个元素开始是原数组对应下标的元素与前一个元素的差&#xff0…

修复OpenHarmony系统相机应用横屏拍照按钮点不到的问题

适配OpenHarmony系统相机应用横屏UI&#xff0c; 相关pr: https://gitee.com/openharmony/applications_camera/pulls/233/files 适配效果 如何安装 编译好的hap提供在附件中 1.预置在源码&#xff0c;随固件安装 2.安装hap hdc shell "mount -o remount,rw /"…

10-Gin 文件上传 --[Gin 框架入门精讲与实战案例]

使用 Gin 框架处理文件上传是一个常见的任务&#xff0c;Gin 提供了简单而直观的方法来处理文件上传。下面将介绍如何用 Gin 实现文件上传功能。 1. 安装 Gin 如果你还没有安装 Gin&#xff0c;可以通过 Go 的包管理工具 go get 来安装&#xff1a; go get -u github.com/gi…

Promise实现原理解析,及实现方法。

Promise原理解析 Promise的介绍原理分析源码实现发布部分全部代码订阅部分基础代码简单发布订阅完整代码测试订阅能力链式调用的实现完整链式调用代码链式调用Promise完整功能代码 Promise的介绍 一&#xff0c;Promise的理解 在JavaScript中&#xff0c;Promise是一种用于处理…

http报头解析

http报文 http报文主要有两类是常见的&#xff0c;第一类是请求报文&#xff0c;第二类是响应报文&#xff0c;每个报头除了第一行&#xff0c;都是采用键值对进行传输数据&#xff0c;请求报文的第一行主要包括http方法&#xff08;GET&#xff0c;PUT&#xff0c; POST&#…

【日常开发】Git Stash使用技巧

文章目录 引言一、git stash 基础命令&#xff08;一&#xff09;存储当前工作区的修改&#xff08;二&#xff09;查看存储列表 二、查看存储的内容&#xff08;一&#xff09;查看特定存储的详细内容&#xff08;二&#xff09;查看特定存储修改的文件列表 三、恢复存储的修改…

微服务保护-sentinel

为什么要有微服务保护&#xff1f; 微服务保护是为了避免微服务雪崩而出现的&#xff0c;每个微服务能处理的请求是有限的&#xff0c;如果一个微服务出现问题导致一个请求进入微服务的时间太久&#xff0c;就会导致大量去请求停滞在微服务内部&#xff0c;这样就会过分占用系统…

【Redis】Redis 典型应用 - 缓存 (cache)

目录 1. 什么是缓存 2. 使用 Redis 作为缓存 3. 缓存的更新策略 3.1 定期生成 3.2 实时生成 4. 缓存的淘汰策略 5. 缓存预热, 缓存穿透, 缓存雪崩 和 缓存击穿 关于缓存预热 (Cache preheating) 关于缓存穿透 (Cache penetration) 关于缓存雪崩 (Cache avalanche) 关…

关于easy-es对时间范围查询遇到的小bug

前言&#xff1a;在使用easy-es之前作为一个小白的我只有es原生查询的基础&#xff0c;在自己通过查看官方文档自学easy-es遇到了一个挫折&#xff0c;其他的还好语法和MybatisPlus差不多&#xff0c;正以为我觉得很快就能入手&#xff0c;在对时间范围的判断就给我当头一棒&am…

从0到机器视觉工程师(一):机器视觉工业相机总结

目录 相机的作用 工业相机 工业相机的优点 工业相机的种类 工业相机知名品牌 光源与打光 打光方式 亮暗场照明 亮暗场照明的应用 亮暗场照明的区别 前向光漫射照明 背光照明 背光照明的原理 背光照明的应用 同轴光照明 同轴光照明的应用 总结 相机的作用 相机…

HTML——53. 创建表单

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>创建表单</title></head><body><!--form标签用于创建一个表单&#xff0c;会将里面的内容一起发送服务器&#xff0c;其结构类似于表格--><!--表…

逐行讲解大模型流式输出 streamer 源码

目录 简介TextStreamer 基础流式输出TextIterateStreamer 迭代器流式输出本地代码模型加载并前端展示streamlit 输出显示gradio 输出显示 vllm 部署模型并前端展示streamlit 输出显示gradio 输出显示 备注 简介 本文详细讲解了大模型流式输出的源码实现&#xff0c;包括TextSt…

java_使用阿里云oss服务存储图片

什么情况下可以使用阿里云oss服务存储图片&#xff1f; 对图片的访问速度有高要求时使用&#xff0c;方便用户快速的&#xff08;比如在网页页面中&#xff09;访问到图像 参考&#xff1a;41 尚上优选项目-平台管理端-商品信息管理模块-阿里云OSS介绍_哔哩哔哩_bilibili 1.…

第5章 共享内存范式:C语言层面

5.1OpenMP 5.1.1OpenMP的介绍 OpenMP三个原则 5.2OpenMP的使用 编译制导指令以#pragma omp 开始&#xff0c;后边跟具体的功能指令&#xff0c;格式如:#pragma omp 指令[子句[,子句].]。常用的功能指令如下: 5.2.1编译制导 5.2.2API和环境变量 具体案例-邻接矩阵 // 本代码…