web-dev-qa-db-ja.com

forループまたは外部ループに戻ります

今日、誰かがJavaのreturnキーワードの不適切な使用に出席しました。何かが配列内にあることを検証するために、単純なforループを作成しました。 arrayが長さnの配列だとすると、これは私のコードでした:

for (int i = 0; i < array.length; ++i) {
    if (array[i] == valueToFind) {
        return true;
    }
}
return false;

誰かが、ループ内でreturnステートメントを使用するとガベージコレクションが誤動作するため、これはあまり良いプログラミングではないと言った。したがって、より良いコードは次のとおりです。

int i = 0;
while (i < array.length && array[i] != valueToFind) {
    ++i;
}
return i != array.length;

問題は、なぜ最初のforループが良い習慣ではないのかを適切に説明できないことです。誰か説明してくれますか?

26
Daan Pape

誰かが私に、ループ内でreturnステートメントを使用するとガベージコレクションが誤動作するため、これはあまり良いプログラミングではないと言った。

それは間違いであり、その人からの他のアドバイスをある程度懐疑的に扱うべきだと示唆しています。

「1つのreturnステートメントのみ」(または、より一般的には、1つの出口ポイントのみ)のマントラisすべてのリソースを自分で管理する必要がある言語では重要です。 1か所でコードをクリーンアップします。

Javaではあまり有用ではありません。返す必要があることがわかったらすぐに(そして戻り値がどうあるべきか)すぐに戻ります。そうすれば読むのが簡単になります-他のメソッド(finallyブロック以外)を解決するためにメソッドの残りの部分を取り込む必要はありません。

58
Jon Skeet

誰かが私に、ループ内でreturnステートメントを使用するとガベージコレクションが誤動作するため、これはあまり良いプログラミングではないと言った。

それはたくさんのゴミです。クラスまたは他の場所でメソッドへの他の参照がない限り、メソッド内のすべてがクリーンアップされます(カプセル化が重要な理由)。経験則として、メソッドが終了する場所を把握する方が簡単だという理由だけで、1つのreturnステートメントを使用する方が一般的には優れています。

個人的に、私は書くだろう:

Boolean retVal = false;
for(int i=0; i<array.length; ++i){
    if(array[i]==valueToFind) {
        retVal = true;
        break; //Break immediately helps if you are looking through a big array
    }
}
return retVal;
6
Mike Thomsen

すべての言語で、任意の関数で単一のreturnステートメントを使用することを推奨する方法論があります。特定のコードでは不可能であっても、そのために努力する人もいますが、最終的には(コードの行数が増えるなど)コードがより複雑になる可能性がありますが、一方では(ロジックの場合など)フロー)。

これにより、ガベージコレクションが混乱することはありません。

あなたが彼を聞きたいなら、それをするより良い方法はブール値を設定することです。

boolean flag = false;
for(int i=0; i<array.length; ++i){
    if(array[i] == valueToFind) {
        flag = true;
        break;
    }
}
return flag;
3
jn1kk

一部の人々は、メソッドには単一の終了点(たとえば、returnが1つだけ)が必要であると主張しています。個人的には、そのルールに固執しようとすると、読みにくいコードが生成されると思います。あなたの例では、探していたものを見つけたらすぐに返してください。それは明確で効率的です。

C2 wikiの引用:

関数に対して単一のエントリと単一の出口を持つことの本来の重要性は、無秩序なgoto SpaghettiCodeとは対照的に、StructuredProgrammingの元の定義の一部であり、それに基づいて明確な数学的分析を可能にしたことです。

構造化プログラミングはその日以来勝ち続けているので、誰もそれを特に気にかけず、ページの残りの部分は構造化プログラミング構成の数学的分析ではなく、主にベストプラクティスと美学などについてです。

2
Óscar López

どちらの場合でも、コードは有効です(つまり、コンパイルおよび実行されます)。

Uniの講師の1人は、どのループにもcontinuereturnステートメント、forまたはwhileを含めることは望ましくないと述べました。これは、コードを調べたときに、ループの全長が実行されるのか、returnまたはcontinueが有効になるのかがすぐにはわからないためです。

ループ内で継続するのはなぜ悪い考えなのですか? を参照してください。

覚えておくべき重要な点は、このような単純なシナリオでは(IMO)問題ではありませんが、戻り値を決定する複雑なロジックがある場合、コードはいくつか。

ガベージコレクションに関しては、なぜこれが問題になるのかわかりません。

1
Insectatorious