2016-03-30 16 views
9

これは私が持っているコードです:IntelliJは "for文がループしない"と不平を言っていますか?

public enum Modification { 
    NONE, SET, REMOVE; 
} 

boolean foo(){ 
    for (S s : sList) { 
     final Modification modification = s.getModification(); 
     switch (modification) { 
      case SET: 
      case REMOVE: 
       return true; 
      /* 
      case NONE: 
       break; 
      */ 
     } 
    } 
    return false; 
} 

そして、上で見たようなコードがある場合は、IntelliJのは言うだろう:

声明「のためには、」ループレス...()は、任意のレポートはありませんforのインスタンス whileおよびdoは、本体が最大でも の実行を保証されています。通常、これはバグの兆候です。

私は次のように変更を加えた場合にのみ、IntelliJのが幸せになります: switch文に含まれていません:ケースNONEがあれば

for (S s : sList) { 
    final Modification modification = s.getModification(); 
    switch (modification) { 
     case SET: 
     case REMOVE: 
      return true; 
     case NONE: 
      break; 
    } 
} 

はなぜループのためにループされていませんか?

+2

を固定しています。私の推測:IntelliJは、実装したすべてのオプションを唯一の可能性のあるものとみなし、すべてが最初の反復でリターンを実行します。 – Stultuske

+0

私はこれらがあなたの唯一の3つのケースだと仮定していますか?したがって、基本的には、最初の2つのうちの1つに当たってすぐに真を返すので、ループしないで、単にデフォルトケースを追加してください。 – AngryDuck

+0

@AlexHall with 'case NONE'何回も繰り返され、再度チェックされます。 –

答えて

6

case SET: 
case REMOVE: 
    return true; 

は同じである:これは、次のコードスニペットはequivelantなります。

列挙型定数NONEは、私は次のオプションが与えられています警告を解決するには変更

にこの列挙スイッチに対応するケースのラベルを必要としません。

  • 追加デフォルトの場合
  • 追加欠落しているcase文
  • のfoo()私は不足しているcase文を追加する場合

は、警告が表示されなくに@SuppressWarnings '不完全なスイッチ' を追加します。 。不足の場合を追加するのと同じことが、 エラー の警告がintellijから消えます。

NONEのステートメントがなければ、2つのケースしか見ることができず、どちらも真を返します。 Modificationの構造とNONEの余分な値を知らなければ、このループはループの最初の繰り返しでtrueを返すように見えます。

もちろん、コンパイラーは、SETとREMOVEよりも多くの値が変更されていることを知っているはずです。そのため、警告は正しいスタイルにすぎません。基本的にあなたのコードは動作しますが、ここで改善する方法があります。

私は、不足している場合ではなく、デフォルトのステートメントを追加することを選択します。これは、より多くの値が後に列挙型に追加される場合に、より将来の証明になります。例えば。

switch (modification) 
{ 
    case SET: 
    case REMOVE: 
    return true; 
    default: 
    break; 
} 

私は個人的には、switch文を使ってfall throughを使用するファンではありません。コードを簡潔にすることで得られるものは、わかりやすいIMHOで失われます。誰かが後に来て、SETとREMOVEの間にケースを追加すると、バグが発生する可能性があります。また、メソッドの途中でreturn文を使用すると、問題が発生する可能性もあります。返却の直前にコードを追加したい場合は、すべての場所が不足する可能性があります。メソッドが非常にシンプルであれば、複数の戻り値はうまくいくが、これは単純な例であると述べているので、このコードブロックが複雑な場合は避けるだろう。

Java 8を使用できるのであれば、これは新しいストリームAPIの最適な使用例です。以下のようなものが動作するはずです。

return sList.stream().anyMatch(
    modification -> (modification==Modification.SET || modification==Modification.REMOVE) 
); 
+0

最高の答えと一緒に行く: – jobbert

+0

ところで、それはエラーメッセージではなく、警告です。 IntelliJが「検査」と呼ぶものです。これは、カーソルを 'for'キーワードの上に置いたときに表示されます。メッセージは誤解を招きます。代わりに、不完全なスイッチに関する警告が表示されるはずですが、いずれの場合でもストリームを使用する機能的スタイルがはるかに優れています。 –

+0

ああ、解明してくれてありがとう、それは警告またはエラーの場合はどちらかの方法を言っていないので、私はちょうどそれがエラーだったと仮定する必要があります。 –

1

私はこれがあなたの唯一の3つのケースだと思いますか?基本的には、最初の2つのうちの1つに当たってすぐに真を返します。したがってループしません。defaultケースを追加してください。良い実践もbtwです。

は、基本的には、それはそれだけ

+0

はい、それらは唯一のケースです。 –

0

あなたのスイッチケースは必ず壊れるか、戻りループを反復することなく、即座に返すdoes notのケースを参照してください傾けます。最初のケースでは、何もしません。falls through。 2番目のケースreturnは、スイッチとループの両方を停止させます。 3番目のケースでは、あなたはbreakスイッチステートメントを停止させます。しかし、forループを止めません(別名、iteratingを続けます)。

具体的な機能をSETケースに追加するか、REMOVENONEケースで動作を変更してください。

public enum Modification { 
    NONE, SET, REMOVE; 
} 

boolean foo(){ 
    for (S s : sList) { 
     final Modification modification = s.getModification(); 
     switch (modification) { 
      case SET: 
       // This case falls through to the REMOVE case 
      case REMOVE: 
       return true; // This statement stops the switch, loop and returns true 
      case NONE: 
       break; // This statement stops the switch and continues the loop. 
     } 
    } 
    return false; 
} 

returnがループを破壊し、関数から値を返すため、あなたのスイッチはNONEケースなしでループされていません。 breakは、スイッチループを中断しますが、forループを継続します。


OPの追加の説明で追加説明。

Falling throughは、停止(breakまたはreturn)に達するまで次のケースが実行されることを意味します。私は日食でこれを試してみましたが、あなたはswitch文のコンパイラの警告で終わる

case SET: 
    return true; 
case REMOVE: 
    return true; 
+0

はい。そのとおりです。 –

+2

@rustedbrainこれはどうして正しいですか? IntelliJは言っていますが、OPのコードは実際に何度もループします。 –

+0

@KlitosKyriacouあなたが質問全体と私の答えを読めば、それは私が言っていることとまったく同じであることが分かります。 –

1

私はその偽陽性と言います。

第1表示: デバッガを使用してコードを実行し、他の変更を加えた要素の前にリストにNONE変更のある要素があると、実際にループします。

第二適応症: あなたが生成されたバイトコードを見てみると、それは(一種の - 正確に同じそのない)にswitch文を変換し、あなたのコード、のIntelliJであることを置く場合

for (S s : sList) { 
    Modification modification = s.getModification(); 
     switch (modification.ordinal()) { 
      case 1: 
      case 2: 
       return true; 
    } 
} 

文句を言わない。

第三適応症: 警告dissappearsあなたがリターン前に追加の文を入れた場合、すなわちSystem.out.println();

switch (modification) { 
    case SET: 
    case REMOVE: 
     System.out.println() 
     return true; 

は、あなたが不足しているケースラベルで検査をだまして、単に警告を無視することができそうです。

1

IntelliJの検査が間違っていると思います。私はJetBrains

編集にそれを報告した:必要のデフォルトのオプションをより多くのIDEのがある

関連する問題