[英]Java for-loop iteration
Consider the following piece of code: 考虑以下代码:
final String str = "1-2-3";
for (int idx = 0; idx < str.split("\\D").length; idx++) {
// do something
}
How many times will this portion of code: str.split("\\\\D")
be executed? 这部分代码: str.split("\\\\D")
将执行多少次? Three times? 三次? Or will the compiler see that as str
is declared as final
, only one call to str.split("\\\\D")
will be enough? 还是编译器会看到将str
声明为final
,仅对str.split("\\\\D")
一次调用就足够了吗?
This might be interesting to you. 这可能对您很有趣。 For this code: 对于此代码:
class Foo {
public static void main(String args[]) {
final String str = "1-2-3";
for (int idx = 0; idx < str.split("\\D").length; idx++) {
}
}
}
the bytecode is: 字节码是:
Compiled from "Foo.java"
class Foo {
Foo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: ldc #2 // String 1-2-3
5: ldc #3 // String \D
7: invokevirtual #4 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
10: arraylength
11: if_icmpge 20
14: iinc 2, 1
17: goto 2
20: return
}
It is clear that split
is executed
three
FOUR times, regardless of the finality of str
, and of invariance of split
. 显然,无论str
的终结性和split
的不变性如何, split
都会执行
三
四次。
JLS 14.14.1.2 states ( Expression
here being the middle bit of the for
statement): JLS 14.14.1.2状态(此处的Expression
for
语句的中间位):
Next, a for iteration step is performed, as follows. 接下来,执行for迭代步骤,如下所示。 If the Expression is present, it is evaluated. 如果存在表达式, 则对其求值。
That means it does it on each iteration step, there is no leeway there in the specification for optimisation. 这意味着它在每个迭代步骤中都执行,优化规范中没有余地。
You can see something similar with the following code: 您可以使用以下代码看到类似的内容:
class Test {
public static int getSeven () {
System.out.println ("called getSeven()");
return 7;
}
public static void main (String[] args){
for (int i = 1; i <= getSeven(); i++) {
System.out.println ("i = " + i);
}
}
}
When you run that, you get: 运行该命令时,您将获得:
called getSeven()
i = 1
called getSeven()
i = 2
called getSeven()
i = 3
called getSeven()
i = 4
called getSeven()
i = 5
called getSeven()
i = 6
called getSeven()
i = 7
called getSeven()
showing that the function is called each time through the loop (including the exit condition). 显示每次通过循环调用该函数(包括退出条件)。
That means your particular case won't call it once or three times, it will actually call it four times, with idx
set respectively to 0
, 1
, 2
and the final check at 3
. 这意味着您的具体情况将不会把它一次或三次,这实际上把它四次 , idx
分别设置为0
, 1
, 2
,并在最后检查3
。
EDIT 编辑
The split method will be executed 3 times to determine the length, BUT this has nothing to do with the fact that the string is final or not. 拆分方法将被执行3次,以确定长度, 但这无关的事实,串最终还是没有。 It would be execute the same even if the strign was not final. 即使争端不是最终的,也将执行相同的命令。
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
String g = "bla bla";
for (int i = 0; i < index(g); i++)
{
System.out.println("Round");
}
}
public static int index(String input)
{
System.out.println("index Called");
return input.length();
}
}
The output will show for each round: index Called 输出将显示每一轮: index Called
How does for loop
works for loop
工作原理
int idx = 0
初始化---> int idx = 0
str.split("\\\\D").length;
条件检查---> str.split("\\\\D").length;
idx++
增量索引idx++
str.split("\\\\D").length;
检查条件str.split("\\\\D").length;
idx < str.split("\\\\D").length()
fails 重复步骤4-6,直到idx < str.split("\\\\D").length()
失败 So every time your idx < str.split("\\\\D").length()
will get executed. 因此,每次您的idx < str.split("\\\\D").length()
将被执行。 I would say it will get execute three times for condition match and one last for condition fail. 我会说条件匹配将执行3次,条件失败则最后执行一次。
There's a 100% sure way to see if a compiler optimizes something - look at the compilation result. 有一种100%确定的方法可以查看编译器是否进行了某些优化-查看编译结果。 I've included the byte code in the response and I think it's pretty obvious - the split method will be executed multiple times in the first case regardless of the final keyword (the invoke virtual line is the split method call, you can understand what is looped by the goto statement). 我已经在响应中包含了字节码,并且我认为这很明显-无论哪种最终关键字,split方法都会在第一种情况下多次执行(invoke virtual行是split方法调用,您可以了解什么是转到goto语句)。
Different compilers MAY behave in a different way, though. 但是,不同的编译器可能以不同的方式运行。 Feel free to retest this on your desired environment (you can view bytecode with 'javap -c classname' 随时在所需的环境上重新测试(您可以使用“ javap -c classname”查看字节码)
public class gti {
public static void main ( String[] args ) {
final String str = "1-2-3";
for (int idx = 0; idx < str.split("\\D").length; idx++) {
// do something
}
}
}
results in: 结果是:
public class gti {
public gti();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: ldc #2 // String 1-2-3
5: ldc #3 // String \D
7: invokevirtual #4 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
10: arraylength
11: if_icmpge 20
14: iinc 2, 1
17: goto 2
20: return
}
while 而
public class gti {
public static void main ( String[] args ) {
final String str = "1-2-3";
int length = str.split("\\D").length;
for (int idx = 0; idx < length; idx++) {
// do something
}
}
}
results in: 结果是:
public class gti {
public gti();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String 1-2-3
2: ldc #3 // String \D
4: invokevirtual #4 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
7: arraylength
8: istore_2
9: iconst_0
10: istore_3
11: iload_3
12: iload_2
13: if_icmpge 22
16: iinc 3, 1
19: goto 11
22: return
}
str.split("\\D") will not split your str string it returns new instance of String[] array. str.split(“ \\ D”)不会分割您的str字符串,它返回String []数组的新实例。 Answer is 3 times str.split("\\D") will be executed. 答案是执行str.split(“ \\ D”)3次。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.