Это долгая дискуссия между мной и моим учителем. Может ли быть ситуация, когда вместо цикла while
/do
- while
можно использовать <<20 > цикл не может? Другими словами, существует ли конкретный случай, когда a for
-loop не будет работать вместо цикла while
; while
/do
- while
каким-либо образом "отличным" от for
?
Существуют ли случаи, когда while/do-while необходимо использовать вместо for?
Ответ 1
Нет, такой ситуации нет. Каждый цикл do
- while
может быть записан в терминах while
-loop (путем выполнения тела один раз перед циклом) и наоборот. В свою очередь, каждый while
-loop
while (X) {
...
}
может быть записано как
for (; X;) {
...
}
то есть. мы опускаем инициализацию и инструкцию инкремента. Мы также можем конвертировать из for
обратно в while
путем правильного размещения инициализации и приращения.
Короче говоря, всегда можно преобразовать из одного варианта цикла в любой из двух других. for
-loops просто дает вам возможность ограничить область действия переменной управления циклом и делать любое увеличение в верхней части. Само собой разумеется, что во многих случаях один конкретный вариант цикла имеет смысл использовать больше, чем другие; каждый из них имеет свои конкретные варианты использования.
Также обратите внимание, что fun не просто заканчивается циклами: он также позволяет преобразовать каждый цикл в рекурсивную функцию и наоборот (хотя на практике могут быть ограничения для этого, например, цикл, который работал нормально, при преобразовании в рекурсивную функцию, создает ошибку).
[I] s
while
/do
-while
каким-либо образом "отличным" отfor
?
Это не так. Например, байт-код следующих двух фрагментов идентичен:
int x = 0;
while (x < 10) {
x++;
}
и
int x = 0;
for (; x < 10;) { // or: for (; x < 10; x++) {}
x++;
}
оба становятся:
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
В комментариях о for
-each были разговоры о том, что они могут быть по существу отличными от других типов циклов. Это абсолютно неверно; for
- все петли представляют собой чистый синтаксический сахар вокруг итераторов (или цикл по массивам). Каждый цикл for
-each также может быть преобразован в каждый из других типов циклов. Вот пример:
for (String s : l) { // l is a list of strings
System.out.println(s);
}
и
String s;
Iterator<String> iter = l.iterator(); // l is a list of strings
while (iter.hasNext()) {
s = iter.next();
System.out.println(s);
}
оба становятся:
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
Ответ 2
Нет, вы всегда можете переписать цикл for как цикл while, и все время выглядите как цикл for.
<init>
while (condition) {
...
<increment>
}
эквивалентно:
for (<init>; <condition>; <increment>) {
...
}
Ответ 3
Другие ответы уже рассмотрели эквивалентность между циклами while
и циклом for
. То есть
while(<expr>) {
<body>
}
эквивалентно
for(;<expr>;) {
}
Обратите внимание, что подобное сокращение может быть выполнено с помощью цикла do
- while
. Любой цикл do
- while
do {
<body>
} while(<expr>);
функционально эквивалентно
for (boolean firstIter = true; firstIter || <expr>; firstIter = false) {
<body>
}
Ответ 4
"Абсолютно"? Я бы сказал, нет. Однако тест после цикла aka do-while, в то время как в Java потребуется довольно запутанное условие "для". Это возвращает к логическому абсолюту: условие должно оценивать true или false.
Так что, хотя я не могу предусмотреть случай, когда компилятор не может манипулировать в выполнении правильной логики, я могу видеть в очень коротком порядке, где любой, кто поддерживает вашу программу, может захотеть, чтобы вы побили камнями (или, возможно, думаете, что уже были).
В соответствующей заметке вы ничего не можете сделать на Java, которая не может быть выполнена на машинных языках. Но есть много и много действительно хороших причин для отказа от использования машинного языка. Большинство из них одинаково применимы, когда вы пытаетесь получить "симпатичный" код. Все это весело и игры, пока вы не по телефону с сердитым клиентом в 0300, или с вашим боссом, или с обоими.