回答:
次のように、同じコードブロックに複数のケースを関連付けると役立つ場合があります。
case 'A':
case 'B':
case 'C':
doSomething();
break;
case 'D':
case 'E':
doSomethingElse();
break;
など。単なる例です。
私の経験では、通常、「フォールスルー」して1つのケースに対して複数のコードブロックを実行するのは悪いスタイルですが、状況によってはそれが使用される場合があります。
// Intentional fallthrough.
改行を省略する場合は、常にコメントを行に追加してください。私の意見では「誤って休憩を忘れるのは簡単」ほど悪いスタイルではありません。PSもちろん、答え自体のような単純なケースではありません。
case
のがそのようにスタックされている場合、コメントは気にしません。それらの間にコードがある場合、はい、コメントはおそらくメリットがあります。
case
:そうのように、case 'A','B','C': doSomething(); case 'D','E': doSomethingElse();
例の間に切れ目を必要とせずに、。Pascalはそれを行うことができます。「caseステートメントは、定数、部分範囲、またはコンマで区切られたそれらのリストである可能性がある各セレクターと順序式の値を比較します。」(wiki.freepascal.org/Case)
JavaはCに由来し、それがCの構文です。
複数のcase文に1つの実行パスのみを持たせたい場合があります。以下は、月の日数を示すサンプルです。
class SwitchDemo2 {
public static void main(String[] args) {
int month = 2;
int year = 2000;
int numDays = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if ( ((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0) )
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
System.out.println("Number of Days = " + numDays);
}
}
間違いだと思います。言語の構成要素break
として、デフォルトと同じくらい簡単で、代わりにfallthrough
キーワードを持っています。私が書いたり読んだりしたコードのほとんどは、すべてのケースの後で中断しています。
continue <case name>
、どのcaseステートメントで続行するかを明示的に指定できるようにすることをお勧めします。
case
現在の中switch
で任意のものを許可すると、これは単にになりますgoto
。;-)
ケースフォールスルーを使用すると、あらゆる種類の興味深いことができます。
たとえば、すべてのケースで特定のアクションを実行したいが、特定のケースではそのアクションと他の何かを実行したいとします。フォールスルーでswitchステートメントを使用すると、非常に簡単になります。
switch (someValue)
{
case extendedActionValue:
// do extended action here, falls through to normal action
case normalActionValue:
case otherNormalActionValue:
// do normal action here
break;
}
もちろん、break
ケースの最後でステートメントを忘れて予期しない動作が発生するのは簡単です。優れたコンパイラーは、breakステートメントを省略すると警告を出します。
コンパイラがスイッチの各コードブロックの後に自動的にbreakステートメントを配置しないのはなぜですか?
ともかく良い(特別同棲することができる)いくつかのケースのための同一のブロックを使用することができるようにする欲求を...
それは歴史的な理由によるものですか?いつ複数のコードブロックを実行しますか?
それは主にCとの互換性のためであり、おそらくgoto
キーワードが地球を歩き回った昔からの古代のハックです。もちろん、Duff's Deviceなどの驚くべきことが可能になりますが、それが賛成か反対かは、せいぜい議論の余地があります。
break
後スイッチcase
Sは、スイッチ文のフォールスルーを回避するために使用されます。興味深いことに、これは、JEP-325を介して実装された、新しく形成されたスイッチラベルによって実現できます。
これらの変更により、さらに説明されbreak
ているようにwith everyスイッチcase
を回避できます。
public class SwitchExpressionsNoFallThrough {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int value = scanner.nextInt();
/*
* Before JEP-325
*/
switch (value) {
case 1:
System.out.println("one");
case 2:
System.out.println("two");
default:
System.out.println("many");
}
/*
* After JEP-325
*/
switch (value) {
case 1 ->System.out.println("one");
case 2 ->System.out.println("two");
default ->System.out.println("many");
}
}
}
上JDK-12と上記のコードを実行し、比較出力として見ることができます
//input
1
// output from the implementation before JEP-325
one
two
many
// output from the implementation after JEP-325
one
そして
//input
2
// output from the implementation before JEP-325
two
many
// output from the implementation after JEP-325
two
そしてもちろん物事は変わらない
// input
3
many // default case match
many // branches to 'default' as well
したがって、同じことをするためにいくつかのケースが必要な場合は、コードを繰り返す必要はありません。
case THIS:
case THAT:
{
code;
break;
}
または、次のようなことができます。
case THIS:
{
do this;
}
case THAT:
{
do that;
}
カスケード方式で。
あなたが私に尋ねれば、本当にバグ/混乱が起こりやすい。
do this
し、do that
このためではなく、ただdo that
そのために?
歴史的な記録に関して言えば、トニー・ホアレは、「構造化プログラミング」革命の最中の1960年代に事件の声明を発明しました。Tonyのcaseステートメントは、ケースごとに複数のラベルをサポートし、悪臭のない自動終了をサポートしましたbreak
。明示的な要件break
は、BCPL / B / Cラインから生まれたものです。Dennis Ritchieは次のように書いています(ACM HOPL-II):
たとえば、BCPLスイッチオンステートメントからエスケープするエンドケースは、1960年代に習得したときに言語に存在していなかったため、BおよびCスイッチステートメントからエスケープするためのbreakキーワードのオーバーロードは、意識的ではなく多様な進化によるものです。変化する。
私はBCPLに関する歴史的な記述を見つけることができませんでしたが、リッチーのコメントは、break
多かれ少なかれ歴史的な事故であったことを示唆しています。BCPLは後で問題を修正しましたが、リッチーとトンプソンはUnixを発明するのに忙しくて、そのような詳細に悩まされることができませんでした:-)
break
は、「複数のコードブロックの実行」を許可することで、この設計を選択する動機にもっと関心があることをすでに知っているようです。他の人はCからJavaへのよく知られた遺産について言及しました、そしてこの回答は研究をCより前の日にさらに押し上げました。最初からこの(非常に原始的ではありますが)パターンマッチングがあればいいのですが。
JavaはCから派生しており、その遺産にはDuff's Deviceと呼ばれる技術が含まれています。これは、break;
ステートメントがない場合に制御が1つのケースから次のケースに移るという事実に依存する最適化です。Cが標準化されたときには、そのようなコードが「実際に」たくさんあり、そのような構文を壊すように言語を変更することは逆効果でした。
前にも言ったように、フォールスルーを許すことで間違いではないのが特徴です。break
ステートメントが多すぎて不快な場合は、return
代わりにステートメントを使用して簡単に取り除くことができます。メソッドは可能な限り小さくする必要があるため(読みやすさと保守性のために)、これは実際には良い習慣であり、switch
ステートメントはすでにメソッドに対して十分な大きさであるため、優れたメソッドには他に何も含めるべきではありません。例:
public class SwitchTester{
private static final Log log = LogFactory.getLog(SwitchTester.class);
public static void main(String[] args){
log.info(monthsOfTheSeason(Season.WINTER));
log.info(monthsOfTheSeason(Season.SPRING));
log.info(monthsOfTheSeason(Season.SUMMER));
log.info(monthsOfTheSeason(Season.AUTUMN));
}
enum Season{WINTER, SPRING, SUMMER, AUTUMN};
static String monthsOfTheSeason(Season season){
switch(season){
case WINTER:
return "Dec, Jan, Feb";
case SPRING:
return "Mar, Apr, May";
case SUMMER:
return "Jun, Jul, Aug";
case AUTUMN:
return "Sep, Oct, Nov";
default:
//actually a NullPointerException will be thrown before reaching this
throw new IllegalArgumentException("Season must not be null");
}
}
}
実行は次のように出力します。
12:37:25.760 [main] INFO lang.SwitchTester - Dec, Jan, Feb
12:37:25.762 [main] INFO lang.SwitchTester - Mar, Apr, May
12:37:25.762 [main] INFO lang.SwitchTester - Jun, Jul, Aug
12:37:25.762 [main] INFO lang.SwitchTester - Sep, Oct, Nov
予想通り。
コンパイラーによって自動ブレークが追加されていないため、スイッチ/ケースを使用して、1 <= a <= 3
1と2からbreakステートメントを削除するなどの条件をテストできます。
switch(a) {
case 1: //I'm between 1 and 3
case 2: //I'm between 1 and 3
case 3: //I'm between 1 and 3
break;
}
それは古い質問ですが、実際には、breakステートメントのないケースを今日使用しました。異なる関数を順番に組み合わせる必要がある場合、ブレークを使用しないことは実際には非常に便利です。
例:http応答コードを使用してタイムトークンでユーザーを認証する
サーバー応答コード401-トークンが古くなっています->トークンを再生成してユーザーをログインさせてください。
サーバー応答コード200-トークンは問題ありません->ユーザーをログインさせてください。
caseステートメントの場合:
case 404:
case 500:
{
Log.v("Server responses","Unable to respond due to server error");
break;
}
case 401:
{
//regenerate token
}
case 200:
{
// log in user
break;
}
これを使用すると、トークンが再生成されるとランタイムがケース200にジャンプするため、401応答でログインユーザー関数を呼び出す必要はありません。
他のタイプの数、月、カウントを簡単に分離できます。
この場合、これはより良い方法です。
public static void spanishNumbers(String span){
span = span.toLowerCase().replace(" ", "");
switch (span){
case "1":
case "jan": System.out.println("uno"); break;
case "2":
case "feb": System.out.println("dos"); break;
case "3":
case "mar": System.out.println("tres"); break;
case "4":
case "apr": System.out.println("cuatro"); break;
case "5":
case "may": System.out.println("cinco"); break;
case "6":
case "jun": System.out.println("seis"); break;
case "7":
case "jul": System.out.println("seite"); break;
case "8":
case "aug": System.out.println("ocho"); break;
case "9":
case "sep": System.out.println("nueve"); break;
case "10":
case "oct": System.out.println("diez"); break;
}
}
私は現在break
、switchステートメントで必要なプロジェクトに取り組んでいます。そうしないと、コードが機能しません。私と一緒に耐えてください、そして私はあなたがbreak
あなたのswitch文で必要な理由の良い例をあなたに与えます。
3つの状態があり、1つはユーザーが数値を入力するのを待機し、2つ目は数値を計算し、3つ目は合計を出力することを想像してください。
その場合、あなたは持っています:
状態を見ると、厳密な順序はstate1から始まり、次にstate3、最後にstate2の順になります。それ以外の場合は、合計を計算せずにユーザー入力のみを印刷します。もう一度明確にするために、ユーザーが値を入力するのを待ってから、合計を計算して出力します。
次にコード例を示します。
while(1){
switch(state){
case state1:
// Wait for user input code
state = state3; // Jump to state3
break;
case state2:
//Print the sum code
state = state3; // Jump to state3;
case state3:
// Calculate the sum code
state = wait; // Jump to state1
break;
}
}
を使用しない場合break
、state1、state2、state3の順に実行されます。しかしbreak
、を使用すると、このシナリオを回避し、正しい手順で順序1で開始し、次に状態3、最後に状態2の順に並べることができます。
break
。