Java Switch に関するちょっとした理論
あなたが道の分岐点で立ち止まった騎士であると想像してください。左に行くと馬を失ってしまいます。正しく行えば知識が得られます。この状況をコードでどのように表現すればよいでしょうか? おそらく、これらの決定を行うために if-thenやif-then-else などの構成要素を使用することはすでにご存じでしょう。
if (turn_left) {
System.out.println("You will lose your horse");
}
if (turn_right) {
System.out.println("You will gain knowledge");
}
else
System.out.println("So you're just going to stand there?");
しかし、もし道が 2 つに分かれるのではなく、10 つに分かれていたらどうなるでしょうか? 「完全に右」、「その少し左」、「もう少し左」など、合計 10 通りの道があるとします。このバージョンで 「if-then-else 」コードがどのように成長するか想像してみてください。
if (option1)
{…}
else if (option2)
{…}
…
else if (optionN) ...
道路に 10 方向の分岐点があるとします (選択肢の数が有限であることがここで重要です)。このような状況に備えて、Java にはswitchステートメントがあります。
switch (ExpressionForMakingAChoice) {
case (Value1):
Code1;
break;
case (Value2):
Code2;
break;
...
case (ValueN):
CodeN;
break;
default:
CodeForDefaultChoice;
break;
}
ステートメントは次のように機能します。
- ExpressionForMakingAChoice が評価されます。次に、switch ステートメントは、結果の値を次の ValueX と (リストされている順序で) 比較します。
- ExpressionForMakingAChoice が ValueX と一致する場合、コロンに続くコードが実行されます。
- Breakステートメントが見つかった場合、制御は switch ステートメントの外に移されます。
- ExpressionForMakingAChoice がどの ValueX とも一致しない場合、制御は CodeForDefaultCase に渡されます。
-
switch ステートメントでは、ExpressionForMakingAChoice のタイプは次のいずれかである必要があります。
- byte、short、char、int。
- Byte、Short、Character、Integer (プリミティブ データ型のラッパー)。
- 文字列。
- 列挙型。
- デフォルトのブロックはオプションです。これが存在せず、ExpressionForMakingAChoice がどの ValueX とも一致しない場合、アクションは実行されません。
- Breakステートメントは必要ありません。これが存在しない場合、最初にBreakが発生するかswitchステートメントが終了するまで、コードは (case ステートメント内のさらなる比較を無視して) 実行され続けます。
- 複数の選択肢に対して同じコードを実行する必要がある場合は、複数の連続するcaseステートメントを指定することで重複を排除できます。
Java で switch ステートメントがどのように使用されるかを見てみましょう。
心配しないでください。理論はもう終わりです。次の例を見ると、すべてがより明確になります。さて、始めましょう。太陽系の惑星に関する天文学の例を見てみましょう。最新の国際的な態度に従って、冥王星は (軌道の性質により) 除外されました。私たちの惑星は、水星、金星、地球、火星、木星、土星、天王星、海王星のように、太陽からの距離に応じて配置されていることを思い出してください。惑星の序数 (太陽からの距離に対する相対値) を受け取り、その惑星の大気の主成分を List<String> として返す Java メソッドを作成しましょう。。いくつかの惑星が同様の大気組成を持っていることを思い出してください。したがって、金星と火星には主に二酸化炭素が含まれています。木星と土星の大気は水素とヘリウムで構成されています。そして天王星と海王星は最後のガスペアにメタンを加えます。これが私たちの関数です:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
List<String> result = new ArrayList<>();
switch (seqNumberFromSun) {
case 1: result.add("No atmosphere");
break;
case 2:
case 4: result.add("Carbon dioxide");
break;
case 3: result.add("Carbon dioxide");
result.add("Nitrogen");
result.add ("Oxygen");
break;
case 5:
case 6: result.add("Hydrogen");
result.add("Helium");
break;
case 7:
case 8: result.add("Methane");
result.add("Hydrogen");
result.add("Helium");
break;
default:
break;
}
return result;
}
同じ大気組成を持つ惑星に対して同じコードを使用していることに注意してください。これは、連続したcaseステートメントを使用して行いました。私たちの故郷の大気の組成を取得したい場合は、引数として 3 を指定してメソッドを呼び出します。
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) returns ["Carbon dioxide", "Nitrogen", "Oxygen"].
Break を試してみる: すべてのBreakステートメント を削除するとどうなるでしょうか? やるだけやってみよう:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
List<String> result = new ArrayList<>();
switch (seqNumberFromSun) {
case 1: result.add("No atmosphere");
case 2:
case 4: result.add("Carbon dioxide");
case 3: result.add("Carbon dioxide");
result.add("Nitrogen");
result.add ("Oxygen");
case 5:
case 6: result.add("Hydrogen");
result.add("Helium");
case 7:
case 8: result.add("Methane");
result.add("Hydrogen");
result.add("Helium");
default:
}
return result;
}
System.out.println(getPlanetAtmosphere(3)) の結果を出力すると、私たちの故郷の惑星がそれほど住みやすいものではないことがわかります。またはそれは?自分で判断してください: [「二酸化炭素」、「窒素」、「酸素」、「水素」、「ヘリウム」、「メタン」、「水素」、「ヘリウム」]。なぜこのようなことが起こったのでしょうか? プログラムは、最初の一致の後、 switchブロックの終わりまでのすべてのcaseステートメントを実行します。
Break ステートメントの過剰な最適化
Breakステートメントとケースを別の方法で配置することでメソッドを改善できることに注意してください。
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
List<String> result = new ArrayList<>();
switch (seqNumberFromSun) {
case 1: result.add("No atmosphere");
break;
case 3: result.add("Nitrogen");
result.add ("Oxygen");
case 2:
case 4: result.add("Carbon dioxide");
break;
case 7:
case 8: result.add("Methane");
case 5:
case 6: result.add("Hydrogen");
result.add("Helium");
}
return result;
}
コードが少なくなったように見えますよね? caseステートメントの順序をいじって再グループ化することで、ステートメントの総数を減らしました。これで、各タイプのガスが 1 行のコードだけでリストに追加されます。最後の例で示したコードは、物事がどのように機能するかを示すことだけを目的としています。この方法でコードを記述することはお勧めしません。このような Java コードの作成者 (他のプログラマーはもちろん) がそれを保守する必要がある場合、これらの case ブロックの形成の背後にあるロジックと switch ステートメントで実行されるコードを再構築するのが非常に困難であることがわかります。
if との違い
ifステートメントとswitchステートメントの外見上の類似点を考慮すると、 switchステートメントは SPECIFIC VALUE に基づいてケースの 1 つを選択するのに対し、if ステートメントには任意のブール式を含めることができることを忘れないでください。コードを設計するときは、このことに留意してください。結論
- if ステートメントでコードが乱雑にならないように、3 つ以上の分岐にcaseステートメントを使用します。
- Breakステートメントを挿入して、特定の値 (case ステートメント) ごとに分岐の論理ブロックを完成させることを忘れないでください。
- switchステートメントの式には、EnumまたはString のほか、いくつかのプリミティブ型を使用できます。
- デフォルトのブロックを覚えておいてください。予期しない値を処理するために使用します。
- パフォーマンスを最適化するには、最も一般的な値に対応するコード分岐をswitchブロックの先頭に移動します。
- caseステートメントの末尾にあるBreakステートメントを削除するなど、「最適化」に夢中にならないでください。そのようなコードは理解しにくく、その結果、保守も困難になります。
GO TO FULL VERSION