私はプログラミングにおけるcontinue
の主な目的を理解しています。それは、次のようなループの残りのステップから抜け出すことができます。
while(condition1){
... code ...
if(!condition2){
continue;
}
... code ...
if(condition3){
break;
}
... code ...
}
Condition2とcondition3は内部コードに依存している可能性があるので、ループステップとは別にエスケープルートを作成すると便利です。しかし、それは、元の条件を再考するように、エスケープルートを構築する代わりにコードをリファクタリングする必要があることを意味します1。
私がいくつかのcontinue
とbreak
のパーツが必要な場合、私は自分のコードに不満を感じます。通常、私はcontinue
なしで作業していて、本当に見逃していません。
私が受け入れることのできるcontinue
とbreak
のもう1つの使用法は最適化ですが、私は上記で述べたように、それについて同じ気持ちをまだ持っています。どういうわけか「GOTOを使う」と感じています。 そうですか、そうでなければ、なぜですか?
修正:continue
は、ループ全体ではなく、ループの1回の反復から抜け出します。
ループの反復の残りをスキップすることは、メソッド呼び出しから早期に戻ることによく似ています(実際、長いループ本体の多くすべきはメソッド呼び出しです)。したがって、「return
初期またはネストされたif
?を使用する」と同じ議論が当てはまります。これは、よく知られている、対立する論争です。この質問についても、コンセンサスが得られるとは思いません。
私の立場は次のとおりです。continue
は理由のあるキーワードです。ほとんどの人がgoto
を悪いと思っているのと同じように、決して悪いわけではありません。
従来のgoto
にはさまざまな形式があり、さまざまな制限があります。 return
、try{} catch{}
、throw
、break
、またはcontinue
。それらはすべて実際にgoto
であり、周囲にいくつかの追加ビットがあります。
continue
またはbreak
をreturnで別のループスタイルにリファクタリングできます。
for (int i = 0; i <= max; i++) {
if(someTest) { continue; }
if(someOtherTest) { continue; }
doStuff;
}
次のように書くことができます:
for (int i = 0; i <= max; i++) {
func();
}
....
void func() {
if(someTest) { return; }
if(someOtherTest) { return; }
doStuff;
}
どちらが読みやすいですか?ええと、私は最初のものはループのコンテキストが失われるからだと主張しがちですが、それ以外は同じです。日常のコードでは、人々がcontinue
をreturn
よりも少なく見える傾向があるというだけのことです。
から Javaチュートリアル:分岐ステートメントbreak
およびcontinue
をラベルとともに使用すると、ほとんどの人が理解するよりも少し強力になります。また、whichループが制御ステートメントによって実行されていることに関して、コードを少し明示的にします。検討してください:
class ContinueWithLabelDemo {
public static void main(String[] args) {
String searchMe = "Look for a substring in me";
String substring = "sub";
boolean foundIt = false;
int max = searchMe.length() - substring.length();
test:
for (int i = 0; i <= max; i++) {
int n = substring.length();
int j = i;
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++) != substring.charAt(k++)) {
continue test;
}
}
foundIt = true;
break test;
}
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
}
continue
とbreak
は、どのループに続くか、またはどのループにブレークするかを指定するラベルと共に使用されることに注意してください(break
のラベルは、1レベルしかないため、必要ありません。 、ただしコードの理解に役立ちます)。
本当にしたい場合は、このコードをできます:
public class Demo {
public static void main(String[] args) {
String searchMe = "Look for a substring in me";
String substring = "sub";
boolean foundIt;
int max = searchMe.length() - substring.length();
foundIt = loop2(searchMe, substring, max);
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
private static boolean loop2(String searchMe, String substring, int max) {
for (int i = 0; i <= max; i++) {
if (loop(searchMe, substring, i)) {
return true;
}
}
return false;
}
private static boolean loop(String searchMe, String substring, int j) {
int n = substring.length();
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++) != substring.charAt(k++)) {
return false;
}
}
return true;
}
}
(確かにそこには不平を言うためのビットがありますが、私はそのリファクタリングを正しく行ったと思います)...しかし、それがあなたに何をもたらすのか本当にわかりません。そして、複数のリターンを持つこれらの2つのメソッドは、「複数のリターンはアンチパターン」群衆(continue
とbreak
がアンチパターン群衆と同じくらい有効なポイントを持つ)の怒りを引きます。 -そして上記のケースでは、おそらくより正当化された怒りも)。はい、これは、他のテストを利用して " 矢印は反パターン "の人々をあなたに面白く見せるように書くこともできます。
continue
はループ内のガードステートメントです。 break
は初期のリターンです。
あまり使われていないからといって、それがアンチパターンになるわけではありません。それは単に人々がそれに慣れていないことを意味します。
余談ですが、goto
はC# でカムバックのビットを見ることができます- 制限あり (C#にはbreak
のようにJavaのようにラベルが付けられていないため、メソッドを抽出する必要がないため、これはコードを書く方法)。