我正在弄乱日食中的东西,令我惊讶的是,我发现这段代码在运行时被终止而没有任何错误/异常
public class Test {
public static void main(String[] args) {
for(int i = 2; i > 0; i++){
int c = 0;
}
}
}
而他的代码一直在执行
public class Test {
public static void main(String[] args) {
for(int i = 2; i > 0; i++){
int c = 0;
System.out.println(c);
}
}
}
尽管两者都应该是永无止境的无限循环。是否有一些我不知道为什么第一个代码片段被终止?
答案 0 :(得分:8)
首先,两个片段都不是无限循环,因为i
一旦通过Integer.MAX_VALUE
就会变为负片。他们只需要很长时间才能运行。
第一个代码片段运行时间要少得多,因为它不需要打印任何内容,并且编译器可能足够聪明,只需优化代码并消除循环,因为它什么都不做。 / p>
测试你的第一个片段,在循环之前和之后添加System.out.println (System.currentTimeMillis ());
,我得到了:
1486539220248
1486539221124
即。它跑不到1秒钟。
略微改变循环:
System.out.println (System.currentTimeMillis ());
for(int i = 2; i > 0; i++){
int c = 0;
if (i==Integer.MAX_VALUE)
System.out.println (i);
}
System.out.println (System.currentTimeMillis ());
我得到了
1486539319309
2147483647
1486539319344
正如您所看到的,从i
增加到0
需要Integer.MAX_VALUE
不到1秒,然后溢出,此时循环终止。
您添加到循环中的打印数量越多,终止所需的时间就越多。例如:
System.out.println (System.currentTimeMillis ());
for(int i = 2; i > 0; i++){
int c = 0;
if (i % 100000000 == 0)
System.out.println (i);
}
System.out.println (System.currentTimeMillis ());
输出:
1486539560318
100000000
200000000
300000000
400000000
500000000
600000000
700000000
800000000
900000000
1000000000
1100000000
1200000000
1300000000
1400000000
1500000000
1600000000
1700000000
1800000000
1900000000
2000000000
2100000000
1486539563232
现在需要3秒钟。
答案 1 :(得分:3)
关键是:此循环没有任何可见的副作用。
因此可以假设编译器正在优化完整循环。另一方面, javac 并不是因为进行大量优化而闻名。因此:让看会发生什么:
javap -c测试
...
public static void main(java.lang.String []);
0: iconst_2
1: istore_1
2: iload_1
3: ifle 14
6: iconst_0
7: istore_2
8: iinc 1, 1
11: goto 2
14: return
显然:循环仍在那里。所以真实的是:你的循环在某些时候由于int溢出而停止;并且你的程序的第一个版本更快地到达那一点(out.println()是一个非常昂贵的操作;与纯数字添加相比)