@CAT_IS_ME (猫は私。)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

switch文とswitch式

解決したいこと

switch文とswitch式をどう区別するのか教えてください

該当するソースコード

public class Sample{
    public static void main(String[] args){
        int a = 2;
        switch(a){
            case 1 -> System.out.println("A");
            case 2 -> System.out.println("B");
            case 3 -> System.out.println("C");
            default -> System.out.println("D");
        };
    }
}

疑問点

上のコードではswitch式として記述されているらしいのですが、switch文なのでは?と思っています。

理由

・switch式は何らかの値を返すために使う(変数の代入やSystem.out.println(switch(a))など)が、上のコードではそのような使い方はしていない。
・14行目のセミコロンはswitch式では必須だが、switch文には使わない(?)
・defaultはswitch式では必須だが、switch文でも使えるため判断基準にならない
・アロー演算子はswitch文でもswitch式でも使えるため判断基準にはならない。

以上のことから、switch式で「Bと表示される」が正解の問題ですが、switch文なので、「14行目でコンパイルエラー」が正しいと思うのですが、私の考えのどこが間違っていますでしょうか。

0 likes

4Answer

文の末尾に余計なセミコロンがあっても無視されるだけなのでコンパイルは通る、という点で間違っています。

しかし switch 式というのもおかしいように思います。式なら以下のように全体をカッコでくくってもいいはずですが、「文ではありません」とコンパイルエラーが出ます。これは一般的にこの位置に式を書くことはできないからです。(1 + 2; などに置き換えても同じエラーが出ることからも分かります。)よって質問のコードでは switch 文として解釈されていると考えるべきです。

    public static void main(String[] args){
        int a = 2;
        (switch(a){
     // ^ エラー: 文ではありません
            case 1 -> System.out.println("A");
            case 2 -> System.out.println("B");
            case 3 -> System.out.println("C");
            default -> System.out.println("D");
        });
    }
1Like

Comments

  1. @CAT_IS_ME

    Questioner

    回答ありがとうございました!
    「switch文とswitch式」と「アロー演算子かコロンか」を混同していたことが原因でした。
    これらは独立していて、マトリックスのように4パターン存在することがわかったので、解決しました!
    結論としては上記のコードは「アロー演算子でシンプルに書いたswitch文」だったようです

前提として厳密に「式」は、式のみでは存在できません。これはuasiさんがご指摘の通りかと思います。
ざっくり結論を書くと、

  • Switch式はExpressionStatementによって、文としても解釈しうるため、元のコードでもコンパイルが通る。つまりは実装上としては式として見て、コンパイル後はほぼ文として扱われる。
  • かっこをつけると式としてしか評価できなくなるため、コンパイルが通らなくなる。

元のSwitchは式を文として使う、ExpressionStatementという概念です。
https://docs.oracle.com/javase/specs/jls/se26/html/jls-14.html#jls-14.8
そのため、「Switch式と同様にコンパイラはチェックし、コンパイルされた姿はほぼSwitch文」のような形を取ります。

uasiさんのケースに関しては、かっこで囲うとParenthesized Expressionsとして解釈されるため、コンパイルエラーになります。そのため、かっこでのコンパイルエラーが式と文を判断する決定的な証拠にはならないです。
https://docs.oracle.com/javase/specs/jls/se26/html/jls-15.html#jls-15.8.5

1Like

Comments

  1. ツッコミありがとうございます。

    System.out.println("Hello world");  // OK
    (System.out.println("Hello world"));  // illegal
    

    なるほど

式は文の構成要素ですので、どちらにも使えるswitchについてはややこしいところですね。

さて、問題のプログラムですが、
言語仕様の 15.28. switch Expressions の章によれば
各分岐に書かれる式で値を示す必要があります。
今回のような画面表示のみを行うもの(void型)ではswitch式の要件を満たしません。
14.11. The switch Statement の要件は満たしているので、
switch文として処理されていると考えていいかと思います。

1Like

Comments

  1. @CAT_IS_ME

    Questioner

    回答ありがとうございました!
    「switch文とswitch式」と「アロー演算子かコロンか」を混同していたことが原因でした。
    これらは独立していて、マトリックスのように4パターン存在することがわかったので、解決しました!
    結論としては上記のコードは「アロー演算子でシンプルに書いたswitch文」だったようです

switch式か文かの区別は値を返しているかになります。
ご提示したコードはprint句を利用しているため、switch句しか解釈出来ないです。
switch式を利用したい場合、下記のように書いてください。

String result = switch (a) {
case 1 -> "A";
case 2 -> "B";
case 3 -> "C";
default -> "D";
};

    System.out.println(result);
0Like

Your answer might help someone💌