流程控制【代码块与作用域】【选择结构】【循环结构】

@


源码:
Gitee https://gitee.com/drip123456/java-se
GIthub https://github.com/Drip123456/JavaSE

专栏: JavaSE笔记专栏

代码块与作用域

在开始流程控制语句之前,我们先来介绍一下代码块和作用域。

不知道各位小伙伴是否在一开始就注意到了,为什么程序中会有一些成对出现的花括号?这些花括号代表什么意思呢?

public class Main {   //外层花括号
    public static void main(String[] args) {   //内层花括号开始
       
    }  //内层花括号结束
}

我们可以在花括号中编写一句又一句的代码,实际上这些被大括号囊括起来的内容,我们就称为(代码块),一个代码块中可以包含多行代码,我们可以在里面做各种各样的事情,比如定义变量、进行计算等等。

我们可以自由地创建代码块:

public static void main(String[] args) {   //现目前这个阶段,我们还是在主方法中编写代码,不要跑去外面写
    System.out.println("外层");
    {   //自由创建代码块
        int a = 10;
        System.out.println(a);
    }
}

虽然创建了代码块,但实际上程序依然是按照从上到下的顺序在进行的,所以说这里还是在逐行运行,即使使用花括号囊括。那咋一看这不就是没什么卵用吗?我们来看看变量。

我们创建的变量,实际上是有作用域的,并不是在任何地方都可以使用,比如:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

变量的使用范围,仅限于其定义时所处的代码块,一旦超出对应的代码块区域,那么就相当于没有这个变量了。

public static void main(String[] args) {
    int a = 10;   //此时变量在最外层定义
    {
        System.out.println(a);   //处于其作用域内部的代码块可以使用
    }
    System.out.println(a);   //这里肯定也可以使用
}

我们目前所创建的变量都是局部变量(有范围限制),后面我们会介绍更多种类型的变量,了解了代码块及作用域之后,我们就可以正式开启流程控制语句的学习了。

选择结构

某些时候,我们希望进行判断,只有在条件为真时,才执行某些代码,这种情况就需要使用到选择分支语句,首先我们来认识一下if语句:

if (条件判断) 判断成功执行的代码;
public static void main(String[] args) {
    int a = 15;
    if(a == 15)    //只有当a判断等于15时,才会执行下面的打印语句
      	System.out.println("Hello World!");
  	System.out.println("我是外层");   //if只会对紧跟着的一行代码生效,后续的内容无效
}

if会进行判断,只有判断成功时才会执行紧跟着的语句,否则会直接跳过,注意,如果我们想要在if中执行多行代码,需要使用代码块将这些代码囊括起来(实际上代码块就是将多条语句复合到一起)所以说,我们以后使用if时,如果分支中有多行代码需要执行,就需要添加花括号,如果只有一行代码,花括号可以直接省略,包括我们后面会讲到的else、while、for语句都是这样的。

public static void main(String[] args) {
    int a = 15;
    if(a > 10) {    //只有判断成功时,才会执行下面的代码块中内容,否则直接跳过
        System.out.println("a大于10");
        System.out.println("a的值为:"+a);
    }
  	System.out.println("我是外层");
}

如果我们希望判断条件为真时执行某些代码,条件为假时执行另一些代码,我们可以在后面继续添加else语句:

public static void main(String[] args) {
    int a = 15;
    if(a > 10) {    //只有判断成功时,才会执行下面的代码块中内容,否则直接跳过
        System.out.println("a大于10");
        System.out.println("a的值为:"+a);
    } else {   //当判断不成功时,会执行else代码块中的代码
        System.out.println("a小于10");
        System.out.println("a的值为:"+a);
    }
    System.out.println("我是外层");
}

if-else语句就像两个分支,跟据不同的判断情况从而决定下一步该做什么,这跟我们之前认识的三元运算符性质比较类似。

那如果此时我们需要判断多个分支呢?比如我们现在希望判断学生的成绩,不同分数段打印的等级不一样,比如90以上就是优秀,70以上就是良好,60以上是及格,其他的都是不及格,那么这种我们又该如何判断呢?要像这样进行连续判断,我们需要使用else-if来完成:

public static void main(String[] args) {
    int score =  2;
    if(score >= 90)    //90分以上才是优秀
        System.out.println("优秀");
     else if (score >= 70)    //当上一级if判断失败时,会继续判断这一级
        System.out.println("良好");
     else if (score >= 60)
        System.out.println("及格");
     else    //当之前所有的if都判断失败时,才会进入到最后的else语句中
        System.out.println("不及格");
}

当然,if分支语句还支持嵌套使用,比如我们现在希望低于60分的同学需要补习,0-30分需要补Java,30-60分需要补C++,这时我们就需要用到嵌套:

public static void main(String[] args) {
    int score =  2;
    if(score < 60) {   //先判断不及格
        if(score > 30)    //在内层再嵌套一个if语句进行进一步的判断
            System.out.println("学习C++");
        else
            System.out.println("学习Java");
    }
}

除了if自己可以进行嵌套使用之外,其他流程控制语句同样可以嵌套使用,也可以与其他流程控制语句混合嵌套使用。这样,我们就可以灵活地使用if来进行各种条件判断了。

前面我们介绍了if语句,我们可以通过一个if语句轻松地进行条件判断,然后根据对应的条件,来执行不同的逻辑,当然除了这种方式之外,我们也可以使用switch语句来实现,它更适用于多分支的情况:

switch (目标) {   //我们需要传入一个目标,比如变量,或是计算表达式等
  case 匹配值:    //如果目标的值等于我们这里给定的匹配值,那么就执行case后面的代码
    代码...
    break;    //代码执行结束后需要使用break来结束,否则会溜到下一个case继续执行代码
}

比如现在我们要根据学生的等级进行分班,学生有ABC三个等级:

public static void main(String[] args) {
    char c = 'A';
    switch (c) {  //这里目标就是变量c
        case 'A':    //分别指定ABC三个匹配值,并且执行不同的代码
            System.out.println("去尖子班!准备冲刺985大学!");
            break;   //执行完之后一定记得break,否则会继续向下执行下一个case中的代码
        case 'B':
            System.out.println("去平行班!准备冲刺一本!");
            break;
        case 'C':
            System.out.println("去职高深造。");
            break;
    }
}

switch可以精准匹配某个值,但是它不能进行范围判断,比如我们要判断分数段,这时用switch就很鸡肋了。

当然除了精准匹配之外,其他的情况我们可以用default来表示:

switch (目标) {
    case: ...
    default:
    		其他情况下执行的代码
}

我们还是以刚才那个例子为例:

public static void main(String[] args) {
    char c = 'A';
    switch (c) {
        case 'A':
            System.out.println("去尖子班!");
            break;
        case 'B':
            System.out.println("去平行班!");
            break;
        case 'C':
            System.out.println("去差生班!");
            break;
        default:   //其他情况一律就是下面的代码了
            System.out.println("去读职高,分流");
    }
}

当然switch中可以继续嵌套其他的流程控制语句,比如if:

public static void main(String[] args) {
    char c = 'A';
    switch (c) {
        case 'A':
            if(c == 'A') {    //嵌套一个if语句
                System.out.println("去尖子班!");
            }
            break;
        case 'B':
            System.out.println("去平行班!");
            break;
    }
}

目前,我们已经认识了两种选择分支结构语句。

循环结构

通过前面的学习,我们了解了如何使用分支语句来根据不同的条件执行不同的代码,我们接着来看第二种重要的流程控制语句:循环语句。

我们在某些时候,可能需要批量执行某些代码:

public static void main(String[] args) {
    System.out.println("伞兵一号卢本伟准备就绪!");   //把这句话给我打印三遍
    System.out.println("伞兵一号卢本伟准备就绪!");
    System.out.println("伞兵一号卢本伟准备就绪!");
}

遇到这种情况,我们由于还没学习循环语句,那么就只能写N次来实现这样的多次执行。但是如果此时要求我们将一句话打印100遍、1000遍、10000遍,那么我们岂不是光CV代码就要搞一下午?

现在,要解决这种问题,我们可以使用for循环语句来多次执行:

for (表达式1;表达式2;表达式3) 循环体;

介绍一下详细规则:

  • 表达式1:在循环开始时仅执行一次。
  • 表达式2:每次循环开始前会执行一次,要求为判断语句,用于判断是否可以结束循环,若结果为真,那么继续循环,否则结束循环。
  • 表达式3:每次循环完成后会执行一次。
  • 循环体:每次循环都会执行一次循环体。

一个标准的for循环语句写法如下:

public static void main(String[] args) {
  	//比如我们希望让刚刚的打印执行3次
    for (int i = 0; i < 3; i++)    //这里我们在for语句中定义一个变量i,然后每一轮i都会自增,直到变成3为止
        System.out.println("伞兵一号卢本伟准备就绪!");   //这样,就会执行三轮循环,每轮循环都会执行紧跟着的这一句打印
}

我们可以使用调试来观察每一轮的变化,调试模式跟普通的运行一样,也会执行我们的Java程序,但是我们可以添加断点,也就是说当代码运行到断点位置时,会在这里暂停,我们可以观察当代码执行到这个位置时各个变量的值:

在这里插入图片描述

调试模式在我们后面的学习中非常重要,影响深远,所以说各位小伙伴一定要学会。调试也很简单,我们只需要点击右上角的调试选项即可(图标像一个小虫子一样,因为调试的英文名称是Debug)
在这里插入图片描述

调试开始时,我们可以看到程序在断点位置暂停了:
在这里插入图片描述

此时我们可以观察到当前的局部变量i的值,也可以直接在下方的调试窗口中查看:

在这里插入图片描述

随着循环的进行,i的值也会逐渐自增:

在这里插入图片描述

i增长到2时,此时来到最后一轮循环,再继续向下运行,就不再满足循环条件了,所以说此时就会结束循环。

当然,如果要执行多条语句的话,只需要使用花括号囊括就行了:

for (int i = 0; i < 3; i++) {
    System.out.println("伞兵一号卢本伟准备就绪!");
    System.out.println("当前i的值为:"+i);
}

注意这里的i仅仅是for循环语句中创建的变量,所以说其作用域被限制在了循环体中,一旦离开循环体,那么就无法使用了

但是我们可以将i的创建放到外面:

public static void main(String[] args) {
    int i = 0;   //在外面创建变量i,这样全部范围内都可以使用了
    for (; i < 3; i++) {   //for循环的三个表达式并不一定需要编写
        System.out.println("伞兵一号卢本伟准备就绪!");
        System.out.println("当前i的值为:"+i);
    }
    System.out.println("当前i的值为:"+i);
}

和之前的if一样,for循环同样支持嵌套使用:

public static void main(String[] args) {
    for (int i = 0; i < 3; i++)    //外层循环执行3次
        for (int j = 0; j < 3; j++)    //内层循环也执行3次
            System.out.println("1!5!");
}

上面的代码中,外层循环会执行3轮,而整个循环体又是一个循环语句,那么也就是说,每一轮循环都会执行里面的整个循环,里面的整个循环会执行3,那么总共就会执行3 x 3次,也就是9次打印语句。

实际上,for循环的三个表达式并不一定需要编写,我们甚至可以三个都不写:

public static void main(String[] args) {
    for (;;)   //如果什么都不写,相当于没有结束条件,这将会导致无限循环
        System.out.println("伞兵一号卢本伟准备就绪!");
}

如果没有表达式2,那么整个for循环就没有结束条件,默认会判定为真,此时就会出现无限循环的情况(无限循环是很危险的,因为它会疯狂地消耗CPU资源来执行循环,可能很快你的CPU就满载了,一定要避免)

当然,我们也可以在循环过程中提前终止或是加速循环的进行,这里我们需要认识两个新的关键字:

public static void main(String[] args) {
    for (int i = 0; i < 3; i++) {
        if(i == 1) continue;   //比如我们希望当i等于1时跳过这一轮,不执行后面的打印
        System.out.println("伞兵一号卢本伟准备就绪!");
        System.out.println("当前i的值为:"+i);
    }
}

我们可以使用continue关键字来跳过本轮循环,直接开启下一轮。这里的跳过是指,循环体中,无论后面有没有未执行的代码,一律不执行,比如上面的判断如果成功,那么将执行continue进行跳过,虽然后面还有打印语句,但是不会再去执行了,而是直接结束当前循环,开启下一轮。

在某些情况下,我们可能希望提前结束循环:

for (int i = 0; i < 3; i++) {
    if(i == 1) break;   //我们希望当i等于1时提前结束
    System.out.println("伞兵一号卢本伟准备就绪!");
    System.out.println("当前i的值为:"+i);
}

我们可以使用break关键字来提前终止整个循环,和上面一样,本轮循环中无论后续还有没有未执行的代码,都不会执行了,而是直接结束整个循环,跳出到循环外部。

虽然使用break和continue关键字能够更方便的控制循环,但是注意在多重循环嵌套下,它只对离它最近的循环生效(就近原则):

for (int i = 1; i < 4; ++i) {
    for (int j = 1; j < 4; ++j) {
        if(i == j) continue;    //当i == j时加速循环
        System.out.println(i+", "+j);
    }
}

这里的continue加速的对象并不是外层的for,而是离它最近的内层for循环,break也是同样的规则:

for (int i = 1; i < 4; ++i) {
    for (int j = 1; j < 4; ++j) {
        if(i == j) break;    //当i == j时终止循环
        System.out.println(i+", "+j);
    }
}

那么,要是我们就是想要终止或者是加速外层循环呢?我们可以为循环语句打上标记:

outer: for (int i = 1; i < 4; ++i) {   //在循环语句前,添加 标签: 来进行标记
    inner: for (int j = 1; j < 4; ++j) {
        if(i == j) break outer;    //break后紧跟要结束的循环标记,当i == j时终止外层循环
        System.out.println(i+", "+j);
    }
}

如果一个代码块中存在多个循环,那么直接对当前代码块的标记执行break时会直接跳出整个代码块:

outer: {    //直接对整个代码块打标签
    for (int i = 0; i < 10; i++) {
        if (i == 7){
            System.out.println("Test");
            break outer;   //执行break时,会直接跳出整个代码块,而不是第一个循环
        }
    }

    System.out.println("???");
}

虽然效果挺奇特的,但是一般情况下没人这么玩,所以说了解就行了。

前面我们介绍了for循环语句,我们接着来看第二种while循环,for循环要求我们填写三个表达式,而while相当于是一个简化版本,它只需要我们填写循环的维持条件即可,比如:

while(循环条件) 循环体;

相比for循环,while循环更多的用在不明确具体的结束时机的情况下,而for循环更多用于明确知道循环的情况,比如我们现在明确要进行循环10次,此时用for循环会更加合适一些,又比如我们现在只知道当i大于10时需要结束循环,但是i在循环多少次之后才不满足循环条件我们并不知道,此时使用while就比较合适了。

public static void main(String[] args) {
    int i = 100;   //比如现在我们想看看i不断除以2得到的结果会是什么,但是循环次数我们并不明确
    while (i > 0) {   //现在唯一知道的是循环条件,只要大于0那么就可以继续除
        System.out.println(i);
        i /= 2;   //每次循环都除以2
    }
}

上面的这种情况就非常适合使用while循环。

和for循环一样,while也支持使用break和continue来进行循环的控制,以及嵌套使用:

public static void main(String[] args) {
    int i = 100;
    while (i > 0) {
        if(i < 10) break;
        System.out.println(i);
        i /= 2;
    }
}

我们也可以反转循环判断的时机,可以先执行循环内容,然后再做循环条件判断,这里要用到do-while语句:

public static void main(String[] args) {
    int i = 0;   //比如现在我们想看看i不断除以2得到的结果会是什么,但是循环次数我们并不明确
    do {  //无论满不满足循环条件,先执行循环体里面的内容
        System.out.println("Hello World!");
        i++;
    } while (i < 10);   //再做判断,如果判断成功,开启下一轮循环,否则结束
}

至此,面向过程相关的内容就讲解完毕了,从下一章开始,我们将进入面向对象编程的学习(类、数组、字符串)

posted @ 2024-02-28 22:25  笠大  阅读(8)  评论(0编辑  收藏  举报