虽然这两种结构通常可以互换,但它们 并非100%等效 !
可以通过定义构造证明,
// pre goes here这将导致两个构造的行为不同。这样的循环体是:
arr = null;
因此,我们现在进行比较:
char[] arr = new char[5];for (char x : arr) { arr = null;}与:
char[] arr = new char[5];for (int i = 0; i < arr.length; i++) { char x = arr[i]; arr = null;}这两个代码都可以编译,但是如果运行它们,您会发现第一个循环正常终止,而第二个循环将抛出
NullPointerException。
这意味着 它们不是100%等效的! 在某些情况下,这两种构造的行为会有所不同!
这种情况可能很少见,但是在调试时不应忘记这一事实,因为否则您可能会错过一些非常细微的错误。
作为附录,请注意,有时for-each构造甚至都不是一个选择,例如,如果您需要索引。这里关键的一点是,
即使可以选择,也需要确保它实际上是等效的替代品,因为不能总是保证
同样,如果从for-each循环开始,后来又意识到需要切换到索引的for循环,请 确保保留语义,因为不能保证 。
尤其要注意对要迭代的数组/集合 的引用 的任何修改( 对内容的
修改可能/可能不会触发
ConcurrentModificationException,但这是一个不同的问题)。
当您使用使用自定义迭代器的集合时,确保语义保留也要困难得多,但是如本示例所示,即使涉及简单数组,这两种构造也是不同的。



