我编写了以下代码来测试java执行从0到大数的简单任务需要多长时间:
public static void main( String[] args )
{
for( long k = 0 ; k <= 1000000000000000000L /* 18 zeros */ ; k++ )
;
System.out.println( "Finished" );
}
Run Code Online (Sandbox Code Playgroud)
我运行程序并等了几个小时.等了这么久以后我除了参考一些计算来估计这个运行时间之外别无他法,并且通过一个简单的计算我确信程序最终可能需要超过100年(取决于CPU)才能最终打印消息"完了"!
但是在尝试下面的代码看起来花费的时间与上面的代码完成时,我意外地看到在完成程序后,在几分之一秒内打印出"完成"消息!
public static void main( String[] args )
{
int j;
for( int i = 0 ; i <= 1000000000 /* 9 zeros */ ; i++ )
for( j = 0 ; j <= 1000000000 /* 9 zeros */ ; j++ )
;
System.out.println( "Finished" );
}
Run Code Online (Sandbox Code Playgroud)
java的行为与这两段代码有什么区别?java的行为与int数字之间必然存在一些差异,并且其行为与int以外的整数类型有关.
其实我认为是编译器的编译优化技术。我不认为这是“Java Behaviour”,它是我们正在讨论的特定Java编译器的行为。
Java 自身的行为在 Java 语言规范中指定,而for 循环规范没有指定任一变量int或long类型变量的优化。
long对于当前的“官方”编译器来说,它将来可能会也可能不会优化增量变量的类型。
-------------------------------- 优化实验
我运行了以下两个程序:
程序1(永远运行):
public static void main( String[] args )
{
long counter = 0L;
int j;
for( int i = 0 ; i <= 1000000000 /* 9 zeros */ ; i++ )
for( j = 0 ; j <= 1000000000 /* 9 zeros */ ; j++ )
counter++;
System.out.println( "Finished" + counter);
}
Run Code Online (Sandbox Code Playgroud)
程序2(立即完成):
public static void main( String[] args )
{
long counter = 0L;
int j;
for( int i = 0 ; i <= 1000000000 /* 9 zeros */ ; i++ )
for( j = 0 ; j <= 1000000000 /* 9 zeros */ ; j++ )
counter++;
System.out.println( "Finished");
}
Run Code Online (Sandbox Code Playgroud)
因此,编译器会检测嵌套循环之外是否有任何可见的变化,如果没有,它基本上会跳过内部循环。