Java 流程控制 -- Java 语言的代码块、作用域、循环与依赖

CSDN 2024-06-14 12:05:03 阅读 97

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 005 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自己的技术栈的同学。与此同时,本专栏的所有文章,也都会准备充足的代码示例和完善的知识点梳理,因此也十分适合零基础的小白和要准备工作面试的同学学习。当然,我也会在必要的时候进行相关技术深度的技术解读,相信即使是拥有多年 Java 开发经验的从业者和大佬们也会有所收获并找到乐趣。

上一篇文章中,我们详细介绍了 Java 数据类型,包括 8 种基本数据类型、字符串与数组。本篇文章我们将深入探讨 Java 的流程控制,包括代码块、作用域、循环与依赖。这些概念是编写高效、清晰代码的关键,对于掌握 Java 编程至关重要。

最后在前言的末尾我补充一下,如果这篇文章,对大家有所帮助或收获一定的乐趣和想法,那么非常欢迎大家能够,点赞、评论、收藏、订阅。这些也将是我持续更新的最大动力。


文章目录

1、块作用域1.1、局部代码块1.2、构造代码块1.3、静态代码块1.4、同步代码块1.5、代码块执行顺序 2、Java 条件语句2.1、条件语句2.2、多重选择 3、Java 循环语句3.1、while/do-while 循环语句3.2、for 循环语句3.3、foreach 循环语句3.4、Java 中断循环


1、块作用域

在 Java 中,块(block,或称为复合语句)是由一对大括号括起来的一组语句。块确定了变量的作用域,即变量在其所在的块中有效。一个块可以嵌套在另一个块中,但不能在嵌套的两个块中声明同名的变量。

有名字的代码块包括 if-else 代码块,for 循环代码块,main 方法代码块等。这些代码块也被称为体,如 for 循环体,main 方法体等。

此外根据代码块位置和声明的不同,块还可以分为可以分为局部代码块,构造代码块,静态代码块和同步代码块。

1.1、局部代码块

在 Java 中,局部代码块通常指的是定义在方法或语句中的代码块。这些代码块的边界由一对大括号 {} 划定。局部代码块主要用于控制变量的生命周期,即变量在其所在的代码块中有效。例如:

public void myMethod() { // 这是一个局部代码块 { int x = 10; // x 的作用域仅限于这个代码块 System.out.println(x); } // 在这里无法访问 x,因为 x 已经超出了其作用域}

在这个例子中,变量 x 的作用域仅限于局部代码块,一旦代码执行超出了这个代码块,变量 x 就会立即从内存中销毁,无法再被访问。

1.2、构造代码块

在 Java 中,构造代码块是定义在类中,方法之外的代码块。每次创建对象时,构造代码块都会被执行,并且在构造方法之前执行。构造代码块主要用于执行所有对象共享的初始化操作。例如:

public class MyClass { // 这是一个构造代码块 { System.out.println("构造代码块被执行"); } public MyClass() { System.out.println("构造方法被执行"); } public static void main(String[] args) { new MyClass(); }}

在这个例子中,当创建 MyClass 的对象时,首先会执行构造代码块,然后才会执行构造方法。因此,运行这段代码会输出:

构造代码块被执行构造方法被执行

这说明构造代码块在构造方法之前被执行。

1.3、静态代码块

在 Java 中,静态代码块是使用 static 修饰的代码块,定义在类中,方法之外。静态代码块在类加载时执行,优先于主方法和构造代码块执行。无论创建多少个对象,静态代码块只执行一次。静态代码块主要用于给静态变量赋值或进行类的初始化操作。例如:

public class MyClass { static { System.out.println("静态代码块被执行"); } { System.out.println("构造代码块被执行"); } public MyClass() { System.out.println("构造方法被执行"); } public static void main(String[] args) { new MyClass(); new MyClass(); }}

在这个例子中,当运行 main 方法时,首先会执行静态代码块,然后每次创建对象时,会执行构造代码块和构造方法。因此,运行这段代码会输出:

静态代码块被执行构造代码块被执行构造方法被执行构造代码块被执行构造方法被执行

这说明静态代码块在类加载时执行,且只执行一次,而构造代码块和构造方法在每次创建对象时都会执行。

1.4、同步代码块

在 Java 中,同步代码块是使用 synchronized 修饰的代码块,主要用于控制多线程的并发访问,确保同一时间只有一个线程可以执行同步代码块中的代码。

以下是一些注意事项:

同步代码块是通过 synchronized 关键字加上一个对象来定义的。这个对象就是同步监视器,线程需要获得这个对象的锁才能执行同步代码块。

synchronized (this) { // 同步代码块} 在多线程环境下,对共享数据的读写操作需要使用同步代码块进行互斥处理,否则可能会导致数据的不一致性;同步代码块需要写在方法中,可以在任何方法中使用,包括 static 方法和实例方法;当一个线程开始执行同步代码块时,它必须先获得对同步监视器的锁定。一旦获得锁,其他线程就无法进入这个同步代码块,直到前一个线程执行完同步代码块并释放同步监视器的锁。

1.5、代码块执行顺序

子类 A 构造函数、子类 A 静态代码块、子类 A 非静态代码块、父类 B 构造函数、父类 B 静态代码块、父类 B 非静态代码块、执行的先后顺序:

父类B静态代码块 > 子类A静态代码块 > 父类B非静态代码块 > 父类B构造函数 > 子类A非静态代码块 > 子类A构造函数

这个顺序是由 Java 的类加载机制和对象初始化过程决定的。在类加载时,静态代码块会被执行,且只执行一次。在创建对象时,首先会执行父类的非静态代码块和构造函数,然后执行子类的非静态代码块和构造函数。


2、Java 条件语句

2.1、条件语句

在 Java 中,if 语句用于根据特定条件执行代码块。基本的 if 语句格式如下:

if (condition) { statement;}

在这里,condition 必须用括号括起来,如果 condition 为 true,则执行 statement。此外,if 语句还可以配合 else 使用,格式如下:

if (condition) { statement1;} else { statement2;}

在这里,如果 condition 为 true,则执行 statement1;否则,执行 statement2。else 子句与最近的 if 构成一组。因此,如果有多个 if 语句,else 会与离它最近的 if 配对。为了避免混淆,可以使用括号明确指定 else 与哪个 if 配对。

在一些情况下,可能需要根据多个条件执行不同的代码块,这时可以使用 if…else if… 结构,例如:

if (condition1) { statement1;} else if (condition2) { statement2;} else { statement3;}

在这里,如果 condition1 为 true,则执行 statement1;否则,如果 condition2 为 true,则执行 statement2;如果两个条件都不满足,执行 statement3。

2.2、多重选择

在 Java 中,switch 语句用于基于一个简单变量的值来执行一条或多条语句。switch 语句的基本格式如下:

switch (variable) { case constant1: statement1; break; case constant2: statement2; break; // ... default: statementDefault;}

在这里,variable 可以是 byte、short、int、char、枚举类型或者从 Java SE 7 开始的字符串类型。case 后面的 constant 必须是 variable 类型的常量或字面量。

switch 语句会根据 variable 的值,选择与之相匹配的 case 子句执行。如果没有找到匹配的 case,则执行 default 子句。

此外,如果 case 子句没有 break,则会继续执行下一个 case,直到遇到 break 或 switch 语句结束。这种情况被称为 “贯穿”(fall through),在某些情况下可能会引发错误,因此通常建议在每个 case 子句后面都加上 break。

public class Main { public static strictfp void main(String[] args) { int a = 1; // 最终打印控制台输出结果为 123 switch (a){ case 1: System.out.println(1); case 2: System.out.println(2); case 3: System.out.println(3); break; case 4: System.out.println(4); case 5: System.out.println(5); } }}


3、Java 循环语句

3.1、while/do-while 循环语句

在 Java 中,while 和 do-while 是两种基本的循环结构。

while 循环的格式如下:

while (condition) { statement;}

在这里,首先会检查 condition,如果 condition 为 true,则执行 statement,然后再次检查 condition,如此循环。如果 condition 为 false,则跳出循环。如果 condition 一开始就为 false,则 statement 一次也不会执行。

do-while 循环的格式如下:

do { statement;} while (condition);

在这里,首先会执行 statement,然后检查 condition,如果 condition 为 true,则继续执行 statement,如此循环。如果 condition 为 false,则跳出循环。因为 do-while 循环先执行 statement,后检查 condition,所以 statement 至少会执行一次。

3.2、for 循环语句

在 Java 中,for 循环是一种常用的循环结构,主要用于执行固定次数的循环。for 循环的格式如下:

for (initialization; condition; update) { statement;}

在这里:

initialization 部分用于初始化循环控制变量;condition 部分是每次循环前要检查的条件,如果 condition 为 true,则执行 statement,否则跳出循环;update 部分用于更新循环控制变量。

虽然 Java 允许在 for 循环的各个部分放置任何表达式,但通常建议遵守一条不成文的规则:for 语句的三个部分应该对同一个循环控制变量进行初始化、检测和更新。这样可以使代码更易于理解和维护。例如:

for (int i = 0; i < 10; i++) { System.out.println(i);}

在这个例子中,循环控制变量 i 在 for 语句的三个部分都有出现,分别用于初始化、检测和更新。这样的 for 循环结构清晰明了,易于理解。

3.3、foreach 循环语句

在 Java 中,for-each 循环(也称为增强 for 循环)是一种简化的循环结构,主要用于遍历数组或集合。for-each 循环的格式如下:

for (variable : collection) { statement;}

在这里,collection 是要遍历的数组或集合,variable 是每次循环时 collection 的当前元素。for-each 循环会依次将 collection 的每个元素赋值给 variable,然后执行 statement。

for-each 循环相比传统的 for 循环更简洁,不需要手动处理下标,因此更不容易出错。例如,以下代码将打印数组 arr 的所有元素:

int[] arr = { 1, 2, 3, 4, 5};for (int num : arr) { System.out.println(num);}

在这个例子中,for-each 循环会依次将 arr 的每个元素赋值给 num,然后打印 num 的值。这样的代码比使用传统的 for 循环更简洁,更易于理解。

3.4、Java 中断循环

在 Java 中,breakcontinuereturn 是用于控制流程的关键字。

break:用于跳出当前循环或 switch 语句,继续执行后面的语句;continue:用于跳过当前循环的剩余部分,直接开始下一次循环;return:用于结束当前方法,并将控制权返回给调用者。如果 return 位于循环内部,会立即结束整个方法,不再执行后面的循环和语句。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。