是否有必须使用while/do-while而不是for?的情况?

REG*_*GAL 23 java for-loop while-loop do-while

这是我和老师之间长期争论的问题.能有一个地方的情况for循环绝对不能被代替的使用while/ do- while循环?换句话说,是否存在一个特定的情况,其中for-loop不能代替while循环; 是while/ do- while以任何方式"不同" for

ars*_*jii 37

不,没有这种情况.每个do- while环可以写在一个方面while-loop(由循环之前执行一次身体),反之亦然.反过来,每一个while循环

while (X) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

可写成

for (; X;) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

即我们省略了初始化和增量语句.我们也可以从一个转换forwhile被正确地安装初始化和增量.

简而言之,始终可以将一个循环变量转换为另外两个循环变量.for-loops只是为了让你能够限制循环控制变量的范围,并在顶部进行任何增量.不言而喻,在许多情况下,一个特定的循环变体使用比其他循环变体更有意义; 每个都有其特定的用例.

还要注意,乐趣并不仅仅以循环结束:它也可以将每个循环转换为递归函数,反之亦然(虽然在实践中可能存在限制;例如,转换为可以正常工作的循环递归函数,产生堆栈溢出错误).


[我] while/ do- while以任何方式"不同" for

它不是.例如,以下两个片段的字节码是相同的:

int x = 0;
while (x < 10) {
    x++;
}
Run Code Online (Sandbox Code Playgroud)

int x = 0;
for (; x < 10;) {  // or: for (; x < 10; x++) {}
    x++;
}
Run Code Online (Sandbox Code Playgroud)

两者都成为:

   0: iconst_0      
   1: istore_1      
   2: goto          8
   5: iinc          1, 1
   8: iload_1       
   9: bipush        10
  11: if_icmplt     5
  14: return 
Run Code Online (Sandbox Code Playgroud)

在评论中有关于for-each循环的讨论,并且它们可能与其他循环类型本质上不同.这绝对不是真的; for-each循环是迭代器周围的纯语法糖(或循环数组).每for-每个环也可以被转换到每个其他环类型.这是一个例子:

for (String s : l) {  // l is a list of strings
    System.out.println(s);
}
Run Code Online (Sandbox Code Playgroud)

String s;
Iterator<String> iter = l.iterator();  // l is a list of strings
while (iter.hasNext()) {
    s = iter.next();
    System.out.println(s);
}
Run Code Online (Sandbox Code Playgroud)

两者都成为:

  24: invokeinterface #33,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
  29: astore_3      
  30: goto          50
  33: aload_3       
  34: invokeinterface #39,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
  39: checkcast     #19                 // class java/lang/String
  42: astore_2      
  43: getstatic     #45                 // Field java/lang/System.out:Ljava/io/PrintStream;
  46: aload_2       
  47: invokevirtual #51                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  50: aload_3       
  51: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
  56: ifne          33
Run Code Online (Sandbox Code Playgroud)

  • @ user2174407:如果您正在尝试向老师证明他们在字节码级别上是等效的,那么无论如何都要显示此响应.但我想你老师正在采取的措施更有可能:"当你可以使用`while(checkIsTrue){...}`来提高阅读能力时,不要使用`;;(checkIsTrue;){...}`清酒." (7认同)
  • 并且`for`和`while`循环只是条件跳转的语法糖! (6认同)
  • @Cruncher不,分支是我熟悉的每个真实世界架构中的基本操作; 它(可选)进行比较,然后用新目标覆盖程序计数器.在JVM中,它是[`if <cond>`](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.if_cond),并且在x86中,它是`J*`操作码.循环实现为编译器管理的跳转模板. (2认同)
  • @PeterOlson我已经描述了do-while如何转换为while,我已经描述了如何转换为for.因此,我还描述了do-while如何转换为for. (2认同)

Ole*_*ksi 6

不,你总是可以将for循环重写为while循环,并且任何时候都看起来像for循环.

<init>
while (condition) {
...
<increment>
}
Run Code Online (Sandbox Code Playgroud)

相当于:

for (<init>; <condition>; <increment>) {
...
}
Run Code Online (Sandbox Code Playgroud)

  • @DennisMeng"等同于"在逻辑上是双条件的(<==>).这意味着两种方式.否则正确的措辞将是"暗示",或"如果这有效,那么这也有效" (2认同)