书接上文,上期我们讲到了分支结构,那么作为它的好兄弟循环结构自然也不能落下,它们经常一起出现在各种代码之中,相互配合相互照应,接下来我们一起来看一下循环:

一、循环结构

        在看循环语句之前,我们先了解一下如何控制它们,主要有三个控制语句

关键字作用对象作用描述是否返回值
break循环、switch立即终止当前循环或 switch
continue循环跳过当前循环体中剩余代码,继续下一次循环
return方法(函数)退出当前方法,可返回一个值

         前两个好理解,那么 return 出现在循环中是什么情况呢?我们拿break和return做一个对比

break:

int[] arr = {2,0,3};
for(int i = 0; i < 3; i++){
    if(arr[i] == 0){
        System.out.println("发现0,退出循环");
        break;    
    }
    System.out.println("当前数字为:" + arr[i]);
}
System.out.println("循环结束");

结果为:

当前数字为2

发现0,退出循环

循环结束

return:

​
int[] arr = {2,0,3};
for(int i = 0; i < 3; i++){
    if(arr[i] == 0){
        System.out.println("发现0,退出循环");
        return;    
    }
    System.out.println("当前数字为:" + arr[i]);
}
System.out.println("循环结束");

​

结果为:

当前数字为2

发现0,退出循环

        return;之后,不光跳出了循环,连当前方法也跳出了,所以不执行循环之外方法之中的那个输出语句

1、for循环(一般用于已知循环次数)

1、基础模版

for (初始化语句; 条件判断; 更新语句) {
    // 循环体:满足条件时执行的代码
}

需要注意的是:

        执行顺序是:初始化语句、条件判断、循环体、更新语句

        初始化语句只在最开始执行一次,不参与后面的循环

        完整顺序就是 初始化语句、条件判断、循环体、更新语句、条件判断、循环体、更新语句...

2、增强型for循环

由于循环经常用来遍历数组或者List、Set等集合,所以针对这种情况有一种增强型for循环:

遍历数组:

int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
    System.out.println("当前数字:" + num);
}

遍历List: 

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println("名字:" + name);
}

 3、Label标签控制多层循环

        此外,for循环在嵌套使用时,为了方便跳出某个循环,还可以在前面加上Label标签:

public class TestLabel {
    public static void main(String[] args) {
        label1: for (int i = 0; i < 5; i++) {
            label2: for (int j = 0; j < 5; j++) {
                if (j == 3) {
                    System.out.println("j == 3,跳出外层循环 label1");
                    break label1;
                }
                System.out.println("i=" + i + ", j=" + j);
            }
            System.out.println("内层循环结束");
        }
        System.out.println("所有循环结束");
    }
}

2、while循环(一般用于循环次数未知)

基础模版

// 初始化语句(可选)
while (条件判断) {
    // 循环体:满足条件时执行的代码

    // 更新语句(通常在循环体内或条件判断前)
}

3、do-while循环(不常用)

基础模版

// 初始化语句(可选)
do {
    // 循环体:至少执行一次

    // 更新语句(可选)
} while (条件判断);

不要忘记do-while语句最后要加“;”

二、易踩坑的点

1、死循环

        一定要确保循环条件最后会变为false,尤其是while循环,记得找到合适的条件判断或break

2、变量作用域问题

        循环中的变量使用前必须初始化,循环内定义的变量是局部变量,仅作用于循环内,不可以在外部使用,想要使用需要在循环外定义

3、循环条件中关于数组长度和下标的问题

        数组索引是从0 开始的,所以数组的索引范围是 0 ~ 数组名.length - 1

        注意:数组是调用的是属性不是方法,所以是.length

                   类的对象调用的才是方法,比如String类的对象用.length()

4、数组越界访问

       假设你循环是for(int i = 0;i < xxx;i++) 一定要仔细比对条件判断的范围,还有循环体中和 i 有关的数据,最简单的例子:

int[] arr = new int[5];
for (int i = 0; i <= arr.length; i++) {  // i <= arr.length 是错的
    System.out.println(arr[i]);
}

修正:

for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

5、忘记更新数组长度(动态数组)   

        如果在循环中修改了数组长度,不能直接使用 数组名.length,建议使用List代替数组,或者及时更新数组

6、使用中间量暂存关键数据,防止循环改变数值        

   比如这个判断一个整数是不是水仙花数,代码中采用 temp 将 a 的值保存下来,防止while循环改变 a 的值之后影响后续使用

public boolean isShuiXianHua(int a){
        int sum = 0;
        int n = 0;
        int temp = a;
        while(a != 0){
            a /= 10;
            n++;
        }

        a = temp;

        while(a != 0){
            int k = a % 10;
            sum += Math.pow(k, n);
            a /= 10;
        }

        return sum == temp;
    }

7、增强型for循环的局限性

无法访问索引

无法修改数组或集合内容

无法倒序遍历

8、尽量不要使用浮点数控制循环

        可能会因为精度问题导致死循环

今天的分享就到这里,欢迎大家评论区补充斧正

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐