Java: for(;;) vs. while(true)

72

标准的while(true)循环和for(;;)有什么区别?

它们是否有任何区别,或者在编译后将映射到相同的字节码?


3
你尝试编译并查看字节码了吗? - David M
3
这是需要翻译的内容:Nothing: http://stackoverflow.com/search?q=for+while+true这段话的意思是:无内容:http://stackoverflow.com/search?q=for+while+true。 - Lasse Espeholt
可能是重复的问题:for(;true;) 不同于 while(true)? - Daniel Fischer
参见:“for(;;)”比“while(TRUE)”更快吗?如果不是,为什么人们会使用它? 这是针对C语言的,但大部分答案仍然适用。 - Boann
9个回答

123
从语义上讲,它们是完全等价的。这只是一个品味问题,但我认为while(true)看起来更干净,更易于一眼阅读和理解。在Java中,它们都不会引起编译器警告。
在字节码级别上,这可能取决于编译器和优化级别,但原则上生成的代码应该是相同的。
编辑:在我的编译器上,使用Bytecode Outline插件,for(;;){}的字节码如下:
   L0
    LINENUMBER 6 L0
   FRAME SAME
    GOTO L0

while(true){} 的字节码如下:

   L0
    LINENUMBER 6 L0
   FRAME SAME
    GOTO L0

对我来说,它们是相同的。


7
感谢您提供代码并说明如何查找它,因此接受了这个答案。谢谢。 :) - sjas
2
在我看来,for(;;)是更简洁的版本(也更短:P)。 - bestsss
1
请注意,在VS中,使用while(true)会在C和C++(C#?)的最高设置下引起编译警告。也许对于Java来说不是问题,但如果你写其他语言的代码,使用for(;;)会是一个更好的习惯。 - T.E.D.
1
在Java源代码中,他们倾向于使用for(;;),所以我只是跟随专业人士的做法:D - Ogen
私有静态最终布尔型常量NO_BREAK等于真。 - Maarten Bodewes

29

这取决于你想使用哪个。因为它们都等同于编译器。

创建文件:

// first test
public class Test {
    public static void main(String[] args) {
        while (true) {
            System.out.println("Hi");
        }
    }
}

编译:

javac -g:none Test.java
rename Test.class Test1.class

创建文件:

// second test
public class Test {
    public static void main(String[] args) {
        for (;;) {
            System.out.println("Hi");
        }
    }
}

编译:

javac -g:none Test.java
mv Test.class Test2.class

比较:

diff -s Test1.class Test2.class
Files Test1.class and Test2.class are identical

我进行了一个小测试。在jd-gui中反编译这些类,显示的是for(;;)而不是while(true) - vedi0boy
@vedi0boy 在 JVM 级别(和字节码)上 - 没有区别,jd-gui 选择最简单的方式来显示这个循环。 - 4ndrew
@4ndrew 当然我知道,我只是好奇反编译器是如何看待它的。似乎 while(true) 不太受欢迎。 - vedi0boy

8

它编译成相同的字节码,取决于你喜欢哪种结构。

我阅读了很多来自Oracle分布式JDK的源代码,我不太容易记得我曾在他们的代码中看到过while(true)语句,但我确实看到了很多for(;;)语句。我个人更喜欢for(;;),我的理由是:

while循环“应该”需要一个布尔表达式,而不是一个布尔常量。while(true)有点像if(true),我认为这两个都只是为了增加大众的舒适感而合法化。空的while()不会编译。在其中添加true感觉有点像黑客行为。

另一方面,for(;;)是一个“真正的循环”,尽管是一个空循环。此外,它还可以为您节省一些按键! =)(虽然这没什么关系

因此,虽然while(true)在英语中读起来更好,但我认为for(;;)更能表达您的意图,并且更符合Java编程语言。无论如何,应该避免永久循环。当我读到for(;;)时,我感到很安全,因为我知道开发人员会在某个地方中断执行路径。当我读到while(true)时,我就不能那么确定了。但是嘿,也许只是我的想法!我们都可以自由选择自己的风格。


你可以写成 while(1==1),这是我认为最简洁的方式。 - JacksOnF1re
1
有点晦涩的知识,但在日期时间教程中他们使用for(;;){}。 - man guy
1
将for(;;)发音为forever。 - Default

6
在Oracle Java 7上,您将获得相同的字节码。从字节码无法确定原始使用了哪个。哪个更好是一个品味问题。我使用while(true)

3

根据编译器的不同,它应该映射到相同的字节码。


3

JVM会找到最佳的方法来生成字节码,在两种情况下应该是相同的。因此,我认为没有区别。while(true)只是更美观。


3
我查看了生成的字节码,发现由于条件始终为真(在编译时),编译器将编译掉测试并总是分支返回到循环顶部。我认为一个continue语句也会总是分支返回到循环顶部。因此,这不仅不会产生任何影响,甚至没有生成任何代码进行测试。

2

从功能上来说,它们没有区别。任何因字节码差异而获得或失去的效率都很可能与您在循环体中运行的任何指令相比微不足道。


1

只需要解析器的时间有所不同,两个不同的表达式包含不同数量的标记需要解析,但计算时间差异非常小,并且两种情况的编译字节码相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接