《Java安全编码标准》一3.3 DCL02-J将所有增强for语句的循环变量声明为final类型

简介: 本节书摘来自华章出版社《Java安全编码标准》一书中的第3章,第3.3节,作者 (美)Fred Long,Dhruv Mohindra,Robert C. Seacord,Dean F. Sutherland,David Svoboda,更多章节内容可以访问云栖社区“华章计算机”公众号查看

3.3 DCL02-J将所有增强for语句的循环变量声明为final类型

Java 5平台(也因for-each风格出名)引入了增强的for语句,它用来对对象集合进行迭代。与基本的for语句不同,在基本的for语句中,给循环变量赋值是不能对循环的迭代次序有所影响。但在增强的for语句中,给循环变量赋值就可以有影响,而不是像程序员通常认为的那样。这使我们认识到应避免给在for循环中的循环变量赋值。
详情请见JLS的14.14.2节“增强的for语句”[JLS 2005]。
一个增强的for循环通常采用以下这种形式:

??for (ObjType obj : someIterableItem) {
????// ...
??}
这等价于以下形式的基本for循环:
??for (Iterator myIterator = someIterableItem.iterator();
???????myIterator.hasNext();) {
???ObjType obj = myIterator.next();
???// ...
??}

所以,一个给循环变量赋值的动作,等价于修改循环体的局部变量的值,这个变量的初始值会被循环迭代器引用。这种修改不一定是错误的,但它会模糊循环的行为,或者意味着对增强型for语句的内在实现,这在理解上有问题。
可以将所有的for语句中的循环变量声明为final。这个final声明可以让Java编译器做一个标志,并且拒绝对这个循环变量的任何赋值。

3.3.1 不符合规则的代码示例

这个不符合规则的代码示例想要使用增强型的for循环处理对象集合。此外,它还希望跳过对集合中某一个元素的处理。

Collection<ProcessObj> processThese = // ...?

for (ProcessObj processMe: processThese) {
??if (someCondition) { // found the item to skip
????someCondition = false;
????processMe = processMe.getNext(); // attempt to skip to next item
??}
??processMe.doTheProcessing(); // process the object
}

这种跳过到下一个集合元素的想法看起来是可以实现的,因为已经成功赋值,并且processMe变量的值也更新了。然而,和基本型的for循环不同,这个赋值并没有改变循环执行的迭代次序。因此,虽然需要跳过的元素跳过了,但是它之后的元素被处理了两次。
注意,如果声明processMe为final,在试图对它进行这样的赋值时,就会产生编译器错误。

3.3.2 符合规则的方案

这个符合规则的方案可以正确地处理在集合中的每一个对象,并且每一个对象只会被处理
一次。

Collection<ProcessObj> processThese = // ...?

for (final ProcessObj processMe: processThese) {
??if (someCondition) { // found the item to skip
????someCondition = false;
????continue; // skip by continuing to next iteration
??}
??processMe.doTheProcessing(); // process the object
}

3.3.3 风险评估

给增强型的for循环的循环变量赋值,不影响整体的迭代次序,这样会导致程序员产生困惑,并且会让数据的状态不一致。
image

自动化检查 这条规则可以很容易通过使用静态分析来实行。

3.3.4 参考书目

[JLS 2005] 14.14.2节 增强的for语句

相关文章
|
30天前
|
Java
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
25 0
|
1月前
|
Java
java中的泛型类型擦除
java中的泛型类型擦除
13 2
|
1月前
|
Java
Java周期循环的代码可以如此简单
Java周期循环的代码可以如此简单
26 2
|
1月前
|
存储 Java
JAVA字符串与其他类型数据的转换
JAVA字符串与其他类型数据的转换
27 4
|
1天前
|
存储 Java
JAVA变量类型
JAVA变量类型
9 0
|
7天前
|
存储 算法 安全
什么是Java泛型类型?
【4月更文挑战第13天】
12 0
什么是Java泛型类型?
|
8天前
|
存储 安全 Java
Java中的容器,线程安全和线程不安全
Java中的容器,线程安全和线程不安全
15 1
|
10天前
|
SQL 安全 Java
Java安全编程:防范网络攻击与漏洞
【4月更文挑战第15天】本文强调了Java安全编程的重要性,包括提高系统安全性、降低维护成本和提升用户体验。针对网络攻击和漏洞,提出了防范措施:使用PreparedStatement防SQL注入,过滤和转义用户输入抵御XSS攻击,添加令牌对抗CSRF,限制文件上传类型和大小以防止恶意文件,避免原生序列化并确保数据完整性。及时更新和修复漏洞是关键。程序员应遵循安全编程规范,保障系统安全。
|
12天前
|
Java
Java 16 新玩法:instanceof 升级版,让类型检查更精准
Java 16 新玩法:instanceof 升级版,让类型检查更精准
13 0
|
12天前
|
存储 监控 安全
泛型魔法:解码Java中的类型参数
泛型魔法:解码Java中的类型参数
33 0
泛型魔法:解码Java中的类型参数