【西行 - 大圣闹天宫】 Java 流程控制

  • J3 - 白起
  • Java(Java基础 # 流程控制 # 笔记)

不论是哪种编程语言,都会提供两种基本的流程控制结构:分支结构和循环结构。

分支结构用于实现根据条件选着性的执行某段代码,循环结构则是用于实现循环条件重复执行某段代码。

Java 中同样提供了这两种流程控制语法:

  • 分支语句:if、switch。
  • 循环语句:while、do while、for 以及JDK1.5 后的 foreach循环。

1、顺序结构

任何编程语言中,最常见的程序结构就是顺序结构。

顺序结构指程序从上到下逐行地执行,中间没有任何判断和跳转。

在 main 方法中多行代码之间没有任何流程控制,则程序总是从上向下一次执行,排在前面的代码先执行,排在后面的代码后执行。

2、分支结构

Java 提供了两种常见的分支控制结构:

  • if
  • switch

if 语句使用布尔表达式或布尔值作为分支条件进行分支控制;而 switch 语句则用于对多个整型值(Java 7 支持String类型)进行匹配,从而实现分支控制。

2.1 if 条件语句

if 语句有下列三种形式。

第一种:

if (条件表达式){
    // 逻辑代码
}

第二种:

if (条件表达式){
    // 逻辑代码
}else {
    // 逻辑代码
}

第三种:

if (条件表达式1){
    // 逻辑代码
}else if (条件表达式2){
    // 逻辑代码
}else if (条件表达式3){
    // 逻辑代码
}
...省略多个 else if 语句
else {
    // 逻辑代码
}

三种类型类型中,条件表达式的返回值只能是 true 或者 false。

在上面的条件语句中,if (表达式) 、else if (表达式) 和 else 后花括号括起来的多行代码被称为代码块,一个代码块通常被当成一个成体来执行(除非运行过程中遇到 return、break、continue 等关键字,或者遇到了异常),因此这个代码块也被称为条件执行体。例如如下代码。

public class BranchTest {

    public static void main(String[] args) {
        
        int age = 18;
        if (age == 18){
            // 只有当 age 等于 18 时下面的两个输出语句才会执行
            System.out.println("噢噢噢!原来 J3 才 18 岁。");
            System.out.println("不愧是靓仔");
        }
        System.out.println("一个毫无意义的输出,就像 J3 还认为自己 18 岁。");
    }
}

如果 if(表达式)、else if(表达式)和 else 后的代码只有一行语句是,则可以省略花括号,因为单行语句本身就是一个整体,无须用括号来把它们定义成一个整体。例如下面代码完全可以执行。

public class BranchTest {

    public static void main(String[] args) {
        
        int age = 17;
        if (age > 18)
            System.out.println("J3 老是拿年龄做文章,都不敢正视自己的年纪!!!");
        else
            System.out.println("嘿嘿!我要让上面的语句不能输出,敢质疑我,哼!");
    }
}

但,通常我们是不建议这样做的,即时条件执行体只有一条语句,也要保留花括号,因为可读性较好,而且这会减少错误发生的可能。

例如下面代码和想象的结果可能有不同。

public class BranchTest {

    public static void main(String[] args) {

        int age = 19;
        if (age > 18)
            System.out.println("J3 老是那年龄做文章,都不敢正视自己的年纪!!!");
        else
            System.out.println("嘿嘿!我要让上面的语句不能输出,敢质疑我,哼!");
            // 这个输出永远会执行
            System.out.println("J3 永远是 18");
    }
}

System.out.println("J3 永远是 18") 这个语句永远会执行的原因就是它不是 else 后的条件执行体。

如果,if 后面有多条语句作为条件执行体,若省略了这个条件执行体的花括号,则会引起编译错误。例如下面代码。

public class BranchTest {

    public static void main(String[] args) {

        int age = 19;
        if (age > 18)
            System.out.println("J3 老是那年龄做文章,都不敢正视自己的年纪!!!");
            System.out.println("这个输出写在这,是会报错的在没有花括号的时候!!!!!");
        else
            System.out.println("嘿嘿!我要让上面的语句不能输出,敢质疑我,哼!");
            // 这个输出永远会执行
            System.out.println("J3 永远是 18");
    }
}

2.2 switch分支语句

switch 语句由一个控制表达式和多个 case 标签组成,和 if 语句不同的是,switch 语句后面的控制表达式的数据类型只能是 byte、short、char、int 四个整数类型和枚举类型,不能是 boolean 类型。

Java 7 改进了 switch 分支语句,Java 7 允许 switch 语句中的控制表达式为 java.lang.String 类型。

switch 语句往往需要在 case 标签后紧跟着一个代码块,case 标签作为这个代码块的标识。语法格式如下。

public class BranchTest {

    public static void main(String[] args) {

        switch (表达式){
            case 情况1:{
                // 逻辑1
                break;
            }
            case 情况2:{
                // 逻辑2
                break;
            }
            ...
            default:{// 都不满足,则默认执行这个
                // 默认逻辑
            }
        }

    }
}

这种分支语句的执行先是对表达式求值,然后依次匹配情况1、情况2、…等值,遇到匹配的值及执行对应的执行体;如果所有 case 标签后的值都不与表达式的值相等,则执行 default 标签后的代码块。

和 if 语句不同的是,switch 语句中各个 case 标签后代码块的开始点和结束点非常清晰,因此完全可以省略 case 后面的花括号。

与 if 语句中的 else 类似,当 switch 表达式中的值没有任何一种情况匹配时,就会执行 default 后面的代码块。

switch 使用案例如下。

public class BranchTest {

    public static void main(String[] args) {

        char name = 'J';

        switch (name){
            case 'A':{
                System.out.println("name 等于 A");
                break;
            }
            case 'B':{
                System.out.println("name 等于 B");
                break;
            }
            case 'J':{
                System.out.println("name 等于 J");
                break;
            }
            default:{
                System.out.println("name 啥也不是!");
            }
        }
    }
}

运行结果输出了 “name 等于 J” 符合我们的预期。

看代码我们发现,每个 case 标签后面都有一条 break;语句,这个 break;语句还是挺重要的,如果把上面代码的 break;都去掉那么结果会是如下情况。

name 等于 J
name 啥也不是!

看起来有点奇怪,但这就是由 switch 语句的运行流程决定的。

switch 语句会先求出表达式的值,然后和 case 标签后的值进行比较,一旦遇到相等的值,就开始执行 cases 标签后面的代码,并不在判断后面 case、default 标签的条件是否匹配,除非是遇到 break;才会结束。

Java 7 增强了 switch 语句的功能,允许 switch 语句的控制表达式是 java.lang.String 类型的变量或者表达式(只允许了 java.lang.String 其他类型字符串不行)。例如如下代码。

public class BranchTest {

    public static void main(String[] args) {

        String blogType = "CSDN";
        switch (blogType){
            case "CSDN":{
                System.out.println("J3,CSDN老牌用户,新人作者!");
                break;
            }
            case "juejin":{
                System.out.println("J3,掘金新用户,新人作者");
                break;
            }
            case "zhihu":{
                System.out.println("J3,知乎新用户,新人作者");
                break;
            }
            default:{
                System.out.println("J3,啥也不是!");
            }
        }
    }
}

在使用 switch 时,有两个地方值得注意:

  • switch 表达式类型只能是 byte、short、char、int、String。
  • 如果 case 标签后的代码省略了 break;则会一直往下执行直到碰到 break;。

3、循环结构

在循环语句中,满足循环条件的情况下,可以反复执行一段代码,重复执行的代码称为循环体。

循环结构需要注意的是,循环条件。当循环条件永远为 true 时会造成死循环。

3.1 while 循环语句

while 循环的语法格式如下:

while (表达式或布尔值) {
    // 循环体代码
}

在执行 while 循环体之前,先对表达式求值,如果条件为 true,则运行循环体部分。

下面演示一个简单的 while 循环。

public class CycleTest {

    public static void main(String[] args) {

        int i = 1;
        int sum = 0;
        while (i <= 10) {
            // 循环,求 1 到 10 的和。
            sum = sum + i;
            i = i + 1;
        }
        System.out.println("1 到 10 的累加和:" + sum);
    }
}

值得注意的是 i <= 10 这个表达式的结果要在某个时刻变为 false ,不然程序会进行死循环,造成程序永远无法结束。

3.2 do while 循环语句

do while 循环与 while 循环的区别在于:while 循环是先判断循环条件,如果条件为真则执行循环体;而 do while 循环则先执行循环体,然后才判断循环条件,如果循环条件为真,则执行下一次循环,否则终止循环。

do while 语法格式如下。

do {
    循环体
}while (表达式);

注意,while 的后面是要跟一个分号,表明循环结束。

下面看看简单用法。

public class CycleTest {

    public static void main(String[] args) {

        int age = 16;
        do {
            System.out.println("时间,一年年的过去,转眼我 J3 已经:" + age + "岁了。");
            age = age + 1;
        } while (age < 25);
        System.out.println("转眼我都这么大了~");
    }
}

由程序我们可以发现,do while 循环不管表达式条件真假,都会执行一遍循环体。

3.3 for 循环

for 循环是一个更加简洁的循环语句,大部分情况下,for 循环可以替代 while 循环、do while 循环。

for 循环的基本语法格式如下。

for (初始化值; 循环条件 ; 迭代语句) {
    循环体
}

程序执行 for 循环时,先执行循环的初始化值,初始化值语句只在循环开始前执行一次。

每次执行循环体之前,先判断循环条件的真假,true 执行循环体,执行循环体完成之后再执行迭代语句。

因为是先判断循环条件真假,在执行循环体,所以循环条件总要比循环体多执行一遍。

简单使用案例如下。

public class CycleTest {

    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 10; i++) {
            sum = sum + i;
            System.out.println("我被执行了第 " + i + " 次。");
        }
        System.out.println("1 到 10 的累加和:" + sum);
    }
}

当然,对于初始化语句是允许指定多个初始语句,循环条件也是可以包含逻辑运算表达式。程序如下。

public class CycleTest {

    public static void main(String[] args) {
        for (int i = 0, b = 2, c = 3; i <= 7 && b < 8 && c < 9; i++) {
            System.out.println("我执行了~~~~~~~");
        }
    }
}

上面代码中初始化变量有三个,但只能有一个声明语句,因此如果需要在初始化表达式中声明多个变量,那么这些变量应该具有相同的数据类型。

在 for 循环括号中只有两个分号是必须的,初始化语句、循环条件、迭代语句部分都是可以省略的,如果省略了循环条件,则这个循环条件模式 true ,将会产生一个死循环。例如下面程序。

public class CycleTest {

    public static void main(String[] args) {
        for (; ; ) {
            System.out.println("我将要进行死循环输出了~~~");
        }
    }
}

上面代码将进行死循环,一直输出 我将要进行死循环输出了~~~ 字符串。

使用 for 循环还是以写成如下形式。

public class CycleTest {

    public static void main(String[] args) {
        // 初始语句
        int i = 1;
        for (; i <= 10 ; ) {
            System.out.println("我是变种 for 循环!");
            // 迭代语句
            i = i +2;
        }
    }
}

这种写法与 while 的形式很类似,并且这种写法的初始值 i 即时在 for 循环体外也是可以访问的,而初始化语句写在括号里面的话,则只能在循环体中使用(变量作用范围,后面介绍)。

3.4 嵌套循环

如果把一个循环放在另一个循环体内,那么就可以形成嵌套循环了,嵌套循环既可以是 for 循环嵌套 while 循环,也可以是 while 循环嵌套 do while 循环…既各种类型的循环都可以作为外层循环,各种类型的循环也可以作为内层循环。

当外层循环的循环次数为 n 次,内层循环的循环次数为 m 次,那么内层循环的循环体实际上需要执行 n * m 次。

嵌套循环执行流程如下图。

在这里插入图片描述

从流程图中我们可以看出,嵌套循环就是把内层循环当成外层循环的循环体。

当只有内层循环的循环条件为 false 时,才会完全跳出内层循环,才可以结束外层循环的当次循环,开始下一次循环,下面看个简单案例。

public class NestedTest {

    public static void main(String[] args) {

        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print( j + " * " + i + " = " + i * j + " ");
            }
            System.out.println("");
        }
    }
}

程序执行结果是一个九九乘法表,通过前面知识积累,相信理解起来不费劲。

实际上,嵌套循环不仅可以嵌套两层,只要你愿意,多少层都是可以的。但不管如何嵌套循环,我们都可以吧内层循环当成外层循环体来对待,区别只是这个循环体包含了需要反复执行的代码。

4、控制循环结构

Java 语言没有提供 goto 语句来控制程序的跳转,这种做法提高了流程控制的可读性,但降低了程程控制的灵活性。

为了弥补这种不足, Java 提供了 continuebreak 来控制循环结构。除此之外,return 可以结束整个方法,当然也就是结束一次循环了。

4.1 break 结束循环

循环的时候我们不一定要等到循环条件为 false 的时候才退出循环,使用 break 就可以强行终止循环。

在循环中,一旦循环体中遇到 break ,系统将完全结束该循环,开始执行循环之后的代码。例如下面程序。

public class NestedTest {

    public static void main(String[] args) {

        for (int i = 1; i <= 10000; i++) {
            System.out.println("我在循环 一万次!");
            if (i == 10){
                System.out.println("让你执行 1 万次,疯了,不行,我要结束你!");
                break;
            }
        }
        System.out.println("结束了");
    }
}

break 语句不仅可以结束其所在的循环,还可以直接结束外层循环。此时需要在 break 后紧跟一个标签,这个标签用于表示一个外层循环。

Java 中的标签就是一个紧跟着英文冒号(:)的标识符。与其他语言不同的是,Java 中的标签只有放在循环语句之前才有作用。例如下面代码。

public class NestedTest {

    public static void main(String[] args) {

        // 外层循环,outo 作为标识符
        outo:
        for (int i = 1; i <= 100; i++) {
            for (int j = 1; j <= 100; j++) {
                System.out.println("我又在循环 1 万次!");
                if ( (i * j) > 10){
                    System.out.println("给你脸了,又来循环 1 万次,给我全部结束,不要执行了!");
                    // 跳出 outo 标签所在标识的循环
                    break outo;
                }
            }
        }
        System.out.println("我结束了!");
    }
}

程序从外层循环进入内层循环后,当 i * j > 10 后,程序遇到一个 break outo;语句,这行代码将会导致结束 outo 标签指定的循环,不是结束 break 所在的循环,而是结束 break 玄幻的外层循环。

通常紧跟 break 之后的标签,必须在 break 所在的循环的外层循环之前定义才有意义。

4.2 continue 结束本次循环

continue 的功能和 break 有点类似,区别是 continue 只是终止本次循环,接着开始下次循环;而 break 则是完全终止循环本身。可以理解为 continue 的作用是跳过当次循环中剩下的语句,重新开始一次新的循环。例如下面代码。

public class NestedTest {

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {

            System.out.println("我是 i = " + i + " 前面的语句");
            if (i <= 3){
                continue;
            }
            System.out.println("我是 i = " + i + " 后面的语句");
        }
    }
}

当 i 小于等于 3 的时候 if 下面的语句没有输出,因为程序走了 if 体里面的 continue ,忽略了当次循环,开始了新循环。

与 break 类似的是,continue 后也可以紧跟一个标签,用于直接跳过标签所在标识循环的当次循环的剩下语句,重新开始下一次循环。例如下面代码。

public class NestedTest {

    public static void main(String[] args) {

        outo:
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j < 5; j++) {
                System.out.println("这人又来 for 循环了~~~");
                if (i * j > 8) {
                    System.out.println("只能执行到这了,下面的就先跳过吧,不用执行了");
                    continue outo;
                }
                System.out.println("内层循环,我是否能被执行到!!!");
            }
            System.out.println("======外层循环,我是否能被执行到!!!");
        }
    }
}

当程序执行到 continue outo 语句时,直接跳过了内层循环和外层循环,执行了外层的下一次循环。

与 break 类似的是,continue 后的标签也必须是一个有效标签,即这个标签通常应该放在 continue 所在循环的外层循环之前定义。

4.3 return 结束方法

return 关键字并不是专门用于结束循环的,return 的功能是结束一个方法。当一个方法执行到 return 语句时(return 关键字后还可以跟变量、常量和表达式,后面会介绍),这个方法将被结束。

例如下面代码会结束改方法。

public class NestedTest {

    public static void main(String[] args) {
        for (int i = 0; i < 100000; i++) {
            System.out.println("我又在不停的循环中...");
            if (i > 10){
                System.out.println("过分,1 万都不让你循环,你还循环 10 次,做梦,我要终结整个方法。");
                return;
            }
        }
    }
}

上面代码,碰到 return 语句后,程序立马结束,不管循环多少次或多少层。

好了,今天的内容到这里就结束了,关注我,我们下期见

查阅或参考资料:

《Java核心技术第10卷》

《疯狂 Java 讲义》

联系方式:

QQ:1491989462,做个好友,来个点赞之交。


  • 由于博主才疏学浅,难免会有纰漏,假如你发现了错误或偏见的地方,还望留言给我指出来,我会对其加以修正。

  • 如果你觉得文章还不错,你的转发、分享、点赞、留言就是对我最大的鼓励。

  • 感谢您的阅读,十分欢迎并感谢您的关注。

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

个人站点:J3

CSDN:J3 - 白起

掘金:J3-白起

知乎:J3-白起

这是一个技术一般,但热衷于分享;经验尚浅,但脸皮够厚;明明年轻有颜值,但非要靠才华吃饭的程序员。

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J3code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值