web-dev-qa-db-ja.com

Java続行ラベルは非推奨ですか?

2つのforがあります。ネストされたforの後に、ネストされたfor内で条件がtrueの場合に実行したくないコードがあります。 breakを使用すると、そのコードが実行されるため、(SCJPで学習したように)の外部にcontinue label;を使用しました。これはJava?昔ながらの?誰かが再帰または何か他のものを使用することを提案しましたが、私にとってこれは完全に正常で、シンプルで、最新で、完璧な方法です。それ。

here:
for (bla bla) {
   for (bla bla) {
      if (whatever) continue here;
   }
// some code I don't want to execute if whatever is true
}

ありがとう

編集:
質問を次のように言い換えると、ネストされた複数のfor間をどのように「ナビゲート」できますか?このアプローチは「推奨される」方法でしょうか?これがSCJPブックに書かれていることだからです。そうでない場合..これは、Katherine SierraBert Batesが間違っていることを意味しますか?

編集2:
continue label;が推奨されないのはなぜですか? OOPまたはJavaの概念または内部動作の答えが欲しいのですが、何がうまくいかないかもしれません..

17
Cosmin Cosmin

答えは:それは異なります。 continueを頻繁に使用している場合は、コードのリファクタリングが必要であることを示している可能性があります。しかし、あなたが与えたシナリオでは、それを使用するのに問題のない場所のようです。

6
Mark Pope

読みやすくするためにリファクタリングします。

例:

if (!checkWhatever()) {
    // some code I don't want to execute if whatever is true
}
boolean checkWhatever() {
    for (bla bla) {
       for (bla bla) {
          if (whatever) return false;
       }
    }
    return true;
}
7
Mikael Vandmo

私はそれが落胆したと言うでしょう。代替案がより複雑であるか、エラーが発生しやすい(つまり、改善されていない)場合でも、有効な用途があります。

4
Peter Lawrey

Edit 2を参照すると、OOよりも古いプログラミングの正統性に違反しているため、常に少し不愉快に見えます:「構造化プログラミング」( http://en.wikipedia.org/wiki/Structured_programming)を参照 )。それはgotoのスマックでもあり、すべての優れたプログラマーは、gotoをコードに入れる場合は告白に行く必要があることを知っています。

コンパイラーが関数の制御フローを分析するのが難しくなるかもしれないという懸念があるかもしれませんが、それは通常効率上の理由で使用される一種のツールです。たとえば、Java.lang.StringのApache実装は、少なくとも最適化を目的としたこの関数でそれを使用します。

/*
 * An implementation of a String.indexOf that is supposed to perform
 * substantially better than the default algorithm if the "needle" (the
 * subString being searched for) is a constant string.
 *
 * For example, a JIT, upon encountering a call to String.indexOf(String),
 * where the needle is a constant string, may compute the values cache, md2
 * and lastChar, and change the call to the following method.
 */
@SuppressWarnings("unused")
private static int indexOf(String haystackString, String needleString,
        int cache, int md2, char lastChar) {
    char[] haystack = haystackString.value;
    int haystackOffset = haystackString.offset;
    int haystackLength = haystackString.count;
    char[] needle = needleString.value;
    int needleOffset = needleString.offset;
    int needleLength = needleString.count;
    int needleLengthMinus1 = needleLength - 1;
    int haystackEnd = haystackOffset + haystackLength;
    outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
        if (lastChar == haystack[i]) {
            for (int j = 0; j < needleLengthMinus1; ++j) {
                if (needle[j + needleOffset] != haystack[i + j
                        - needleLengthMinus1]) {
                    int skip = 1;
                    if ((cache & (1 << haystack[i])) == 0) {
                        skip += j;
                    }
                    i += Math.max(md2, skip);
                    continue outer_loop;
                }
            }
            return i - needleLengthMinus1 - haystackOffset;
        }

        if ((cache & (1 << haystack[i])) == 0) {
            i += needleLengthMinus1;
        }
        i++;
    }
    return -1;
}
2
ahcox

内側のループを独自のメソッドに配置して、読みやすくするためにリファクタリングします。

for (bla bla) {   
  DoStuff();
}
void DoStuff() {
  for (bla bla) {
    if (whatever) return;
  }
  // some code to execute when whatever is false.
}

原則:メソッドが複雑になり、ブロックのLABELINGが必要になる場合は、ラベルが不要になるように、そのメソッドの一部を別のメソッドにリファクタリングすることを検討してください。

同様に、3つのループであるメソッドを深くすることは賢明ではありません。ループが非常に単純でない限り。ラベルが不要な場合でも。他のメソッド内に複雑さを隠すことにより、最も外側のフロー構造(ループ、if/else、またはスイッチ)が読みやすいことを確認してください。それらのメソッドが1か所からしか呼び出されない場合でも。

1
ToolmakerSteve

'success'などと呼ばれるブール値を使用します。読みやすく、フローをたどる方がはるかに簡単です。 Gotosは、エラー処理にのみ使用する必要があります。

boolean success = true;
for(int outer = 0; (outer <= outerLimit) && sucess; outer++)
{
    for(int inner = 0; (inner <= innerLimit) && success; inner++)
    {
        if( !doInnerStuff() )
        {
            success = false;
        }
    }

    if( success )
    {
        success = doOuterStuff();
    }
}
0
Evvo