每个Java与常规的Java是否相同? [英] Java for each vs regular for -- are they equivalent?

查看:126
本文介绍了每个Java与常规的Java是否相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  char [] arr = new char [5]; 
for(char x:arr){
// code goes here
}

比较:

  char [] arr = new char [5]; 
for(int i = 0; i< arr.length; i ++){
char x = arr [i];
//代码在这里
}

if我把两个循环(和他们编译)的主体完全相同的代码,他们会表现完全一样吗?




完整免责声明:这受到另一个问题的启发( Java :这两个代码是相同的吗?我的答案原来不是答案,但我觉得Java的确切语义 - 每个都有一些需要指出的细微差别。

虽然这两个结构通常是可以互换的,但它们并不是100%等同的!



通过定义 //代码在这里这会导致这两个结构行为不同。一个这样的循环体是:

  arr = null; 

因此,我们现在比较:

  char [] arr = new char [5]; 
for(char x:arr){
arr = null;

$ / code $ / pre



  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循环,那么确保你保留了语义,因为它不能保证。 p>

特别的,_be对于正在被迭代的数组/集合的引用进行任何修改都很谨慎(修改为内容可能/不会触发 ConcurrentModificationException ,但是这是一个不同的问题)。

保证语义保存也是更多当使用使用自定义迭代器的集合时很困难,但正如这个例子所示,即使涉及简单的数组,这两个构造也是不同的。


Are these two constructs equivalent?

char[] arr = new char[5];
for (char x : arr) {
    // code goes here
}

Compared to:

char[] arr = new char[5];
for (int i = 0; i < arr.length; i++) {
    char x = arr[i];
    // code goes here
}

That is, if I put exactly the same code in the body of both loops (and they compile), will they behave exactly the same???


Full disclaimer: this was inspired by another question (Java: are these 2 codes the same). My answer there turned out not to be the answer, but I feel that the exact semantics of Java for-each has some nuances that needs pointing out.

解决方案

While often the two constructs are interchangeable, THEY ARE NOT 100% EQUIVALENT!!!

A proof can be constructed by defining // code goes here that would cause the two constructs to behave differently. One such loop body is:

arr = null;

Therefore, we are now comparing:

char[] arr = new char[5];
for (char x : arr) {
    arr = null;
}

with:

char[] arr = new char[5];
for (int i = 0; i < arr.length; i++) {
    char x = arr[i];
    arr = null;
}

Both code compiles, but if you run them, you will find that the first loop terminates normally, while the second loop will throw a NullPointerException.

This means that they are not 100% equivalent! There are scenarios where the two constructs will behave differently!

Such scenarios are likely to be rare, but this fact should not be forgotten when debugging, because otherwise you might miss some really subtle bugs.


As an addendum, note that sometimes the for-each construct is not even an option, e.g. if you need the index. The crucial lesson here is that even if it's an option, you need to make sure that it's actually an equivalent substitute, because it's not always guaranteed

Similarly, if you start with a for-each loop and later realized that you need to switch to the indexed for loop, make sure that you're preserving the semantics, because it's not guaranteed.

In particular, _be wary of any modification to the reference of the array/collection being iterated_ (modification to the content may/may not trigger ConcurrentModificationException, but that's a different issue).

Guaranteeing semantics preservation is also a lot more difficult when you use collections that use custom iterators, but as this example shows, the two constructs are different even when simple arrays are involved.

这篇关于每个Java与常规的Java是否相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆