调用 Iterator.remove 可能会失败¶
ID: java/iterator-remove-failure
Kind: problem
Security severity:
Severity: warning
Precision: medium
Tags:
- reliability
- correctness
- logic
Query suites:
- java-security-and-quality.qls
Iterator
接口的 remove
方法是一个可选操作。不可修改集合的迭代器或由 Arrays.asList
方法构造的列表的迭代器不支持该方法。在这种迭代器上调用 remove
将导致 UnsupportedOperationException
。
建议¶
如果要在构造后修改集合,请使用可修改的集合类型,例如 ArrayList
或 HashSet
。
示例¶
在以下示例中,构造函数 A(Integer...)
将字段 A.l
初始化为 Arrays.asList(is)
。虽然 Arrays.asList
返回的列表类型支持通过 set
方法更新元素,但它不支持删除元素。因此,在第 20 行调用 iter.remove
在运行时一定会失败。
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class A {
private List<Integer> l;
public A(Integer... is) {
this.l = Arrays.asList(is);
}
public List<Integer> getList() {
return l;
}
public static void main(String[] args) {
A a = new A(23, 42);
for (Iterator<Integer> iter = a.getList().iterator(); iter.hasNext();)
if (iter.next()%2 != 0)
iter.remove();
}
}
为了避免这种失败,请将 Arrays.asList
返回的列表复制到新创建的 ArrayList
中,如下所示
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public class A {
private List<Integer> l;
public A(Integer... is) {
this.l = new ArrayList<Integer>(Arrays.asList(is));
}
public List<Integer> getList() {
return l;
}
public static void main(String[] args) {
A a = new A(23, 42);
for (Iterator<Integer> iter = a.getList().iterator(); iter.hasNext();)
if (iter.next()%2 != 0)
iter.remove();
}
}
参考资料¶
Mark Needham: Java: 被 java.util.Arrays.asList 愚弄。