Fail fast 或 Fail early 是一种软件工程概念,它试图通过在不应该发生的事情发生时立即停止执行来防止复杂问题的发生。在之前的博文和演示文稿中,我更详细地介绍了这种方法的优点,在这篇博文中,我将详细介绍这种想法在 Java 8 中的另一种用法。在 Java 中,迭代器由 Collection 类返回,例如ArrayList、HashSet、Vector 等都是快速失败的。这意味着,如果您在迭代底层数据结构时尝试对其进行 add() 或 remove() 操作,您将得到一个 ConcurrentModificationException。让我们来看看:
import static java.util.Arrays.asList; List ints = new ArrayList<>(asList(1,2,3,4,5,6,9,15,67,23,22,3,1,4,2)); for (Integer i: ints) { // some code ints.add(57); // throws java.util.ConcurrentModificationException }
在 Java 8u20 中,Collections.sort() API 也是快速失败的。这意味着您也不能在迭代中调用它。例如:
import static java.util.Arrays.asList; List ints = new ArrayList<>(asList(1,2,3,4,5,6,9,15,67,23,22,3,1,4,2)); for (Integer i: ints) { // some code Collections.sort(ints); // throws java.util.ConcurrentModificationException }
这是有道理的。迭代数据结构并在迭代期间对其进行排序不仅违反直觉,而且可能导致不可预测的结果。现在,如果您在排序调用后立即中断,您就可以摆脱这个并且不会得到异常。
import static java.util.Arrays.asList; List ints = new ArrayList<>(asList(1,2,3,4,5,6,9,15,67,23,22,3,1,4,2)); for (Integer i: ints) { // some code Collections.sort(ints); // throws java.util.ConcurrentModificationException break; }
但是,这算不上什么好代码。尽量避免旧的 skool 迭代,并尽可能使用 Lambdas。但是,如果您遇到困难,只需在迭代之外进行排序
import static java.util.Arrays.asList; List ints = new ArrayList<>(asList(1,2,3,4,5,6,9,15,67,23,22,3,1,4,2)); Collections.sort(ints); for (Integer i: ints) { // some code }
或者使用在添加时排序的数据结构。
Collections.sort() API 的这一新行为出现在 Java 8 第 20 版中。值得一看的是详细介绍 API 更改的特定部分:
”
区域:core-libs/java.util.collections 概要:Collection.sort defers now defers to List.sort
以前 Collection.sort
将要排序的列表元素复制到一个数组中,对该数组进行排序,然后使用数组中的那些元素更新列表,并使用默认方法 List.sort
推迟到 Collection.sort。这是一个非最佳安排。
从 8u20 版本开始,Collection.sort
遵从 List.sort
。这意味着,例如,使用 Collection.sort
实例调用 ArrayList
的现有代码现在将使用 ArrayList 实现的最佳排序。
”
我认为,如果 Oracle 在此处更明确地说明此更改如何导致运行时问题,那将会有所帮助。考虑到每个人都在使用 Collections 框架,如果以前没有抛出异常的 API 现在可以用于相同的情况(错误的代码和它的所有内容),那么发行说明让开发人员更容易找到该信息会更好.
标签2: Java教程地址:https://www.cundage.com/article/jcg-fail-early-java-8.html