定时任务场景下的代码审查:continue和return的滥用可能引发潜在bug

news2025/1/18 11:43:35

文章目录

      • 前言
      • for 循环中的continue,break和return
      • 实际业务中的滥用
      • 总结
      • 写在最后

前言

在最近的代码审查中,有帮忙审查了组里一个刚毕业1年不到的应届生,发现他写的其中一段代码将for循环中的break、continue、return滥用,导致了一个潜在的bug风险,这个风险后文我们再来分析。

在这里插入图片描述

for 循环中的continue,break和return

在讲解我实际碰到的业务例子之前,先来简单看看下面的例子

for循环是一种常用的编程结构,它可以重复执行一段代码,直到满足某个条件为止。在for循环中,有时我们需要根据不同的情况,跳过当前的迭代,结束当前的循环,或者结束整个方法。为了实现这些功能,Java语言提供了三个关键字:continue,break和return。

  • continue关键字的作用是跳过当前的迭代,继续执行下一次的迭代。例如,如果我们想要打印出1到10之间的所有奇数,我们可以使用如下的代码:
for (int i = 1; i <= 10; i++) {
  if (i % 2 == 0) { // 如果i是偶数,跳过当前的迭代
    continue;
  }
  System.out.println(i); // 打印出i的值
}
输出结果为:
1
3
5
7
9
  • break关键字的作用是结束当前的循环,跳出循环体。例如,如果我们想要打印出1到10之间的所有奇数,但是当i等于5时,就停止打印,我们可以使用如下的代码:
for (int i = 1; i <= 10; i++) {
  if (i == 5) { // 如果i等于5,结束当前的循环
    break;
  }
  if (i % 2 == 0) { // 如果i是偶数,跳过当前的迭代
    continue;
  }
  System.out.println(i); // 打印出i的值
}
输出结果为:
1
3
  • return关键字的作用是结束当前的方法,并返回一个值(如果有的话)。例如,如果我们想要计算1到10之间的所有奇数的和,我们可以使用如下的代码:
public static int sumOddNumbers() {
  int sum = 0; // 初始化和为0
  for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) { // 如果i是偶数,跳过当前的迭代
      continue;
    }
    sum += i; // 把i的值加到sum上
  }
  return sum; // 返回sum的值
}
调用该方法的结果为:
25

然而,在使用continue,break和return关键字时,我们需要注意一些潜在的bug。一个常见的bug是在for循环中使用return关键字,导致循环提前结束,而不是跳过当前的迭代。例如,如果我们想要打印出1到10之间的所有奇数,但是错误地使用了return关键字,我们会得到如下的代码:

我后面讲到的实际例子跟这个基本一样,就是错误滥用了return!

public static void printOddNumbers() {
  for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) { // 如果i是偶数,错误地使用了return关键字
      return;
    }
    System.out.println(i); // 打印出i的值
  }
}
调用该方法的结果为:
1

这是因为当i等于2时,return关键字会结束整个方法,而不是跳过当前的迭代。这样,我们就无法打印出后面的奇数。为了避免这个bug,我们应该使用continue关键字,而不是return关键字。

实际业务中的滥用

上面那是很简单的例子,但在实际公司复杂的业务逻辑中,continue、break和return语句的误用可能导致更严重的错误,甚至难以追踪和修复。

接下来我给出我审查代码中的错误例子:

//定时任务每3分钟执行一次此方法
handleFileItemList(){
	//查询出所有未处理的文件列表---  文件标识flag=0未处理的
    List<FileItem> fileItemList = getFileItemList();  
    //遍历列表,将对应的文件信息赋值到某个页面
    for (FileItem item : fileItemList) {
            ......	
            if(满足此文件信息已经存在于对应页面){
                //将此文件的flag标识置为已处理--flag=1
                setFileItemFlag();
                return;
            }
            .......
            将对应文件信息赋值到某个页面
            setFileInfo2Page();
            //将此文件的flag标识置为已处理--flag=1
            setFileItemFlag();
            .......
         }

}

注意这是一个定时任务的场景: 这里先从DB拉取一个文件信息表,这个文件表有个flag标识此文件是否已经处理过(flag:1已处理,0未处理),对表里面的List数据进行遍历,将对应的文件信息赋值到某个页面,他这里有个判断,如果某个文件信息已经存在于对应的页面了(除了定时任务场景,还会有别的场景会把文件信息赋值到页面),就停止循环,同时将此文件的flag标识置为已处理,直接return!

这个return处理方式说实话,如果一直没人去审查,也不会出现bug,因为针对这个场景是定时任务的,这里因为提前return了,导致后续的FileItem都无法进行处理,但是他会每3分钟执行一次,顶多是执行得慢一点,总能处理完!,如果是别的场景,这个bug应该早就能发现了!

总结

continue,break和return关键字在for循环中的防止乱用的总结如下:

  • continue关键字的作用是跳过当前的迭代,继续执行下一次的迭代。它可以用来跳过某些不需要执行的情况,或者优化循环的效率。
  • break关键字的作用是结束当前的循环,跳出循环体。它可以用来提前终止循环,或者跳出嵌套的循环。
  • return关键字的作用是结束当前的方法,并返回一个值(如果有的话)。它可以用来返回方法的结果,或者提前退出方法。
  • 在for循环中使用return关键字,会导致循环提前结束,而不是跳过当前的迭代。这可能会导致逻辑错误,或者丢失部分结果。为了避免这个bug,我们应该使用continue关键字,而不是return关键字。
  • 在嵌套的for循环中使用continue,break和return关键字,会导致循环的层级混乱。这可能会导致逻辑错误,或者输出错误的结果。为了避免这个bug,我们应该注意它们的作用范围,或者使用标签(label)来指定跳转的目标循环。

写在最后

  • 代码这东西就是这样,一个return 、一个continue,实际上代表的意义千差万别。

  • 像上面的bug,在普通的场景里面其实自己测试的时候可能就很好发现,但是如果在定时任务里面,不去好好审查一下代码,实际上不容易发现,因为最终文件信息都能去赋值到页面里面,只是慢一点而已。但是这也造成了一定的性能损失,明明一次定时任务就可以处理完所有文件,就因为return 的滥用,可能要好几次定时任务才能执行完毕。

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

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

相关文章

口碑超好高质量经典小说,收获无数赞誉,完结多年还是热门之作

经典好文&#xff0c;小郑来为您推荐五本值得一读的好书&#xff0c;这些书籍不仅可以让您的时间不再无聊&#xff0c;还能让您在阅读中获得更多的知识和乐趣。 《传说管理局》 这本书的世界观严谨且庞大&#xff0c;充满了科幻和玄幻元素。如果您喜欢科幻和玄幻类型的书籍&am…

力扣:149. 直线上最多的点数(Python3)

题目&#xff1a; 给你一个数组 points &#xff0c;其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱…

记一次heapdump泄漏获取服务器权限

文章目录 一、漏洞原因二、漏洞利用三、漏洞进一步利用1、工具下载2、通过关键字查询3、通过配置redis的默认账号和密码进行登录4、添加定时计划任务,进行反弹shell5、成功获取服务器的shell补充四、总结五、免责声明一、漏洞原因 扫描目录发现某个spring框架存在大量泄露信息…

DBeaver关闭代码的提示

在DBeaver中会遇到如下现象&#xff0c;很烦&#xff0c;怎么取消这个提示框呢&#xff1f; 解决方案&#xff1a;

第二章 02Java基础-数据类型、标识符、键盘录入

文章目录 前言一、数据类型二、标识符三、键盘录入总结前言 今天我们学习Java基础,数据类型、标识符、键盘录入 一、数据类型 1.数据类型大体上可以分为两类,一类是基本数据类型,另外一类是引用数据类型。今天我们学习基本数据类型。 2.基本数据类型可以分为四类八种,整…

一看就懂,原来这就是计算机网络

引言 计算机网络&#xff0c;听上去很专业的样子&#xff0c;其实我们可以换种思维来理解。 正文 什么是计算机网络&#xff1f; 下图就是计算机网络&#xff0c;所有能联网的设备连接在一起就组成了互联网 计算机网络有什么用&#xff1f; 计算机网络的作用就是用于设备之…

VueX mapState、mapGetters、mapActions和mapMutaions 的使用

一、mapState和mapGetters 如果我们想要读取VueX中的State数据的Getters数据时&#xff0c;需要使用$store.state.数据名 和 $store.getters.数据名。 当我们State和getters中的数据多了以后&#xff0c;书写会很麻烦&#xff1a; 如果我们想要使用方便可以配置计算属性来简化…

Arduino设置SoftwareSerial缓冲区大小

SoftwareSerial的缓冲区大小设置 概述修改缓冲区的大小实验 概述 新的Arduino的ESP8266软串口的缓冲区原来老的库中有宏定义可以用来修改接收和发送缓冲区的大小。在现在新的库中已经没有这个设置了&#xff0c;那怎么才能修改缓冲区的大小哪&#xff1f; 修改缓冲区的大小 …

5.2用队列实现栈(LC225-E)

算法&#xff1a; 其实这道题不用像上一道题一样&#xff0c;用两个队列实现栈。 由于队列的数据结构特性。用一个队列就可实现栈。 难点还是在出队的时候&#xff1a; 比如队列[1,2,3]&#xff0c;要模拟一个栈入栈就是直接append&#xff08;其实就是C中的push&#xff0…

creating server tcp listening socket 127.0.0.1:6379: bind No error

window下启动redis服务报错&#xff1a; creating server tcp listening socket 127.0.0.1:6379: bind No error 解决方案如下按顺序输入如下命令即可连接成功 redis-cli.exeshutdownexit运行&#xff1a;redis-server.exe redis.windows.conf shutdown出现以下错误&#xff…

数据结构之队的实现

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

变压器那些事

电磁感应 电磁感应效应是指当一个导体或线圈处于变化的磁场中时&#xff0c;会在导体或线圈中产生感应电动势或感应电流的现象。 根据法拉第电磁感应定律&#xff0c;当一个导体或线圈被置于变化的磁场中时&#xff0c;通过该导体或线圈的磁通量会发生变化&#xff0c;从而在…

零代码复现-TCGA联合GEO免疫基因结合代谢基因生信套路(一)

经过一段时间的积累&#xff0c;搭建的分析平台已经日渐进入稳定的状态&#xff0c;很多粉丝也在和我们反馈&#xff0c;让我们出一下零代码生信套路课。 小编找了很久&#xff0c;发现某某机构出的TCGA联合GEO 免疫基因代谢基因的生信套路&#xff0c;该套路应用常见相对来说…

【音视频 | opus】opus编码的Ogg封装文件详解

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

【SpringCloud Alibaba -- Nacos】Linux 搭建 Nacos 集群

搭建 Nacos 集群 架构 centos安装docker https://docs.docker.com/engine/install/centos/ 详细配置过程 MySql8 mysql数据库配置 数据库脚本 nacos/conf/nacos-mysql.sql Nacos2 application.properties 修改为mysql spring.datasource.platformmysqldb.num1 db.url…

【算法挑战】字符的最短距离(含解析、源码)

821.字符的最短距离 https://leetcode-cn.com/problems/shortest-distance-to-a-character/ 821.字符的最短距离 题目描述解法 1&#xff1a;中心扩展法 思路复杂度分析代码 (JS/C) 解法 2&#xff1a;空间换时间 思路复杂度分析代码 (JS/C) 解法 3&#xff1a;贪心 思路复杂…

阿里大佬:DDD 领域层,该如何设计?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&#xff1f…

C语言 程序环境 编译和链接

目录 1.程序的翻译环境和执行环境 2.详解C语言程序的编译和链接 2.1翻译环镜 2.2翻译的几个阶段 2.2.1预编译 2.2.2编译 词法分析 符号汇总 2.2.3汇编 生成符号表 2.3链接 1.合并段表 2.合并符号表和重定位 2.4运行环境 1.程序的翻译环境和执行环境 在ANSI C的任…

【网络协议】聊聊DNS协议如何域名解析和负载均衡

DNS 服务器 我们知道如果使用IP地址进行访问网站&#xff0c;很难进行记忆&#xff0c;所以DNS的作用是将域名转换成对应的IP地址。如果全世界都使用同一台DNS服务器&#xff0c;那么DNS服务器本身需要保证服务的高可用、高性能&#xff0c;以及分布式等。最好的方式就是分层。…

日语动词三分类

所有的动词原形都是由う段结尾 50音图 一类动词 一类动词又称五段动词&#xff08;う段动词&#xff09; 1.结尾是う段非る的动词 ます形规律&#xff1a;う段 > 同行的い段ます 日文平假名ます形中文書くかく書きます写探すさがす探します寻找勝つかつ勝ちます胜利遊ぶ…