switchのパターン・マッチング

Java®言語仕様バージョン17.0.11+7-LTS-207への変更

このドキュメントでは、switchのパターン・マッチング(Java SE 17のプレビュー機能)をサポートするためにJava言語仕様に加えられた変更について説明します。この機能の概要は、JEP 406を参照してください。

変更は、JLSの既存のセクションについて説明しています。新しいテキストはこのように示され、削除されたテキストはこのように示されます。必要に応じて、説明と考察が端の方にグレーのボックスで囲まれて記載されています。

JEP 409では、sealedクラスをJava SE 17で最終機能にすると提案しています。これは、switch文および式のswitchブロックに設定される条件に影響を与えます。sealedクラスの詳細な説明は、完全性を期すためにここに含まれています。

変更ログ:

2021-06-08:

2021-05-27:

2021-05-14:

2021-04-30:

第6章: 名前

6.3 宣言のスコープ

6.3.1 式のパターン変数のスコープ

6.3.1.6 switch

次のルールルールは、switchルールで構成されたswitchブロック(14.11.1)があるswitch式(15.28)に適用されます。

次のルールは、switchラベルが付いた文グループで構成されたswitchブロック(14.11.1)があるswitch式に適用されます。

6.3.2 文のパターン変数のスコープ

6.3.2.6 switch

次のルールルールは、switchルールで構成されたswitchブロック(14.11.1)があるswitch文(14.11)に適用されます。

次のルールは、switchラベルが付いた文グループで構成されたswitchブロック(14.11.1)があるswitch式に適用されます。

6.3.3 パターンのパターン変数のスコープ

6.3.3.1 ガード付きパターン

次のルールは、ガード付きパターンp && eに適用されます。

6.3.4 Switchラベルのパターン変数のスコープ

パターン変数は、パターンを持つswitchラベルによって導入でき、関連付けられたswitch式(6.3.1.6)またはswitch文(6.3.2.6)の関連部分のスコープにあります。

次のルールは、switchラベルに適用されます。

第14章: ブロックおよび文

14.11 switch

switch文は、式の値に応じて、いくつかの文または式の1つに制御を転送します。

SwitchStatement:
switch ( Expression ) SwitchBlock

Expressionセレクタ式と呼ばれます。セレクタ式の型はcharbyteshortintCharacterByteShortIntegerStringまたはenum型(8.9)である必要があり、そうでない場合、コンパイル時にエラーが発生します。

セレクタ式の型のこれらの制限は、次のセクションに定義されている、セレクタ式と互換性があるというswitchブロックの概念に含まれるようになりました。

14.11.1 Switchブロック

switch文およびswitch式(15.28)の両方の本体は、switchブロックと呼ばれます。このサブセクションでは、switch文またはswitch式のどちらに出現するかに関係なく、すべてのswitchブロックに適用される一般的なルールを示します。他のサブセクションでは、switch文のswitchブロック(14.11.2)またはswitch式のswitchブロック(15.28.1)のいずれかに適用される追加ルールを示します。

SwitchBlock:
{ SwitchRule {SwitchRule} }
{ {SwitchBlockStatementGroup} {SwitchLabel :} }
SwitchRule:
SwitchLabel -> Expression ;
SwitchLabel -> Block
SwitchLabel -> ThrowStatement
SwitchBlockStatementGroup:
SwitchLabel : {SwitchLabel :} BlockStatements
SwitchLabel:
case CaseConstant {, CaseConstant}
default
SwitchLabel:
CaseOrDefaultLabel {: CaseOrDefaultLabel }
CaseOrDefaultLabel:
case CaseLabelElement {, CaseLabelElement }
default
CaseLabelElement:
CaseConstant
Pattern
null
default
CaseConstant:
ConditionalExpression

switchブロックは次のいずれかで構成できます。

すべてのswitchルールおよびswitchラベルが付いた文グループは、switchラベルで開始し、これはcaseラベルまたはdefaultラベルのいずれかです。1つ以上のcaseまたはdefaultラベルを使用します。caseラベルには、1つ以上のcaseラベル要素があります。複数のswitchラベルが、1つのswitchラベルが付いた文グループに許可されます。switchラベルは、caseラベル要素があるcaseラベルを使用する場合、caseラベル要素を持ちます。

caseラベルには、1つ以上のcase定数があります。すべてのcase定数は、定数式(15.29)またはenum定数の名前(8.9.1)のいずれかである必要があり、そうでない場合、コンパイル時にエラーが発生します。

Switchラベルおよびそのcase定数は、switchブロックに関連付けられていると言い表されます。switchブロックに関連付けられている2つのcase定数が同じ値を持つことはなく、そうでない場合、コンパイル時にエラーが発生します。

switchラベルがswitchブロックの最後に表示される場合、複数のcaseまたはdefaultラベルで構成されているときは、コンパイル時にエラーになります。

switchルールのswitchラベルが複数のcaseまたはdefaultラベルで構成されている場合、コンパイル時にエラーになります。

つまり、case 1: case 2 -> ...は有効なswitchルールではありませんが、case 1, 2 -> ...と書くことができます。

switchブロックのすべてのswitchラベルについて、次のすべてが当てはまる必要があり、そうでない場合、コンパイル時にエラーが発生します。

これらのルールはswitchラベルの形式を制限します。複雑さの多くは、文グループのswitchラベル内のcaseラベル要素を結合する2つの方法のサポートが原因です(たとえば、case 1: case 2およびcase 1,2)。

switchラベルは、defaultラベルを使用するかdefault caseラベル要素がある場合、default switchラベルと呼ばれます。

switchラベルは、両方のswitchラベルが適用される値があり、明白なプリファレンスがない場合、別のswitchラベルより優先されると言い表されます。優先を決定するルールは次のとおりです。

switchブロック内のswitchラベルが、switchブロック内の後続のswitchラベルより優先される場合、コンパイル時にエラーになります。

次の両方が当てはまるswitchラベルが付いた文グループで構成されるswitchブロックに文がある場合、コンパイル時にエラーになります。

  1. パターンがパターン変数を導入するパターンのcaseラベル要素を持つswitchラベルでラベル付けされています。

  2. switchブロック内で前に文があり、その文を正常に完了できます(14.22)。

この条件は、switchラベルで宣言されたパターン変数がスコープ内にあるが、成功したパターン・マッチングがない、switchラベルが付いた文に到達する可能性を除外するために必要です。たとえば、型パターンInteger iを持つswitchラベルでラベル付けされた文に、先行する文グループから到達できるため、パターン変数iは初期化されません。

Object o = "Hello";
switch (o) {
    case String s:  
        System.out.println("String: " + s ); 
    case Integer i: 
        System.out.println(i + 1);    // Error! Can be reached 
                                      // without matching switch label
}

次の両方が当てはまる場合、switchブロック内のswitchラベルで使用されるすべてのcaseラベルがeと互換性がある場合、switch文またはswitch式のswitchブロックは、セレクタ式T e互換性があります。次のように、caseラベルが持つすべてのcaseラベル要素がeと互換性がある場合、そのcaseラベルはeと互換性があります

switch文またはswitch式のswitchブロックは、セレクタ式の型と互換性がある必要があり、そうでない場合、コンパイル時にエラーが発生します。

switch式またはswitch文に次の両方が当てはまる場合、コンパイル時にエラーになります。

  1. switchブロックにデフォルトswitchラベルがあり、

  2. パターンがセレクタ式の型の合計であるパターンのcaseラベル要素を持つswitchブロックにswitchラベルがあります(14.30.3)。

セレクタ式の合計であるパターンは、すべての値に一致するため、デフォルトswitchラベルのように動作します。

次の定義は、sealedクラス(Java SE 17で確定されるJEP 409によって提示される機能)の存在を前提としています。

次のいずれかが保持される場合のみ、型TsealedクラスまたはインタフェースCサポートします

次のいずれかが当てはまる場合、switchブロックは型T対象とします

switchブロックがセレクタ式の型を対象とする場合、switch文または式は網羅的です。

いくつかのパターンの意味は照合先の式の型によって決定されるため、switchラベルに出現するパターンは解決される必要があります(14.30.2)。

switchブロックは、すべてのパターンのcaseラベル要素pが、パターンが型Uでパターンpを解決した結果であるパターンのcaseラベル要素と置換されることを除いて同一のswitchブロックになる型U解決されます

switch文の実行(14.11.3)およびswitch式の評価(15.28.2)の両方で、解決されたswitchブロックのswitchラベルがセレクタ式の値と一致する適用されるかどうかを決定する必要があります。解決されたswitchブロックのswitchラベルが指定された値と一致するに適用されるかどうかを決定するにはの決定は、値がswitchブロックに関連付けられているcase定数と比較され、次のとおりです。次のようになります。

case switchラベルは、いくつかのcase定数定数のcaseラベル要素を含む持つことができます。ラベルは、その定数のいずれかがセレクタ式の値と一致等しい場合、セレクタ式の値と一致しますに適用されます。たとえば、次のコードで、enum変数dayが表示されているenum定数のいずれかである場合、case switchラベルは一致します。

switch (day) {
    ...
    case SATURDAY, SUNDAY :
        System.out.println("It's the weekend!");
        break;
    ...
}

nullは、定数式ではないためcase定数として使用できません。case nullが許可されている場合でも、そのcase内のコードを決して実行できないため、好ましくありません。つまり、セレクタ式が参照型(すなわち、Stringまたはボックス化プリミティブ型またはenum型)である場合、セレクタ式が実行時にnullに評価されると例外が発生します。Javaプログラミング言語の設計者の判断では、caseラベル一致がない、またはdefaultラベル一致がないより、例外を伝播するほうがよい結果になります。

CおよびC++で、switch文の本体は文(単数および複数)にすることができ、caseラベルをその文で直接含む必要はありません。単純なループを考えてみましょう。

for (i = 0; i < n; ++i) foo();

ここでnは正であると知られています。ダフスデバイスとして知られているトリックは、ループをアンロールするためにCまたはC++で使用できますが、これはJavaプログラミング言語では有効なコードではありません。

int q = (n+7)/8;
switch (n%8) {
    case 0: do { foo();    // Great C hack, Tom,
    case 7:      foo();    // but it's not valid here.
    case 6:      foo();
    case 5:      foo();
    case 4:      foo();
    case 3:      foo();
    case 2:      foo();
    case 1:      foo();
            } while (--q > 0);
}

幸いにも、このトリックは広く認識または使用されてはいないようです。さらに、今日ではあまり必要ではなくなりました。この種のコード変換は、適切に最新式の最適化コンパイラの領域にあります。

14.11.2 switch文のSwitchブロック

switchブロック(14.11.1)の一般的なルールに加えて、switch文のswitchブロックにはさらにルールがあります。

拡張switch文は、(i)セレクタ式の型がcharbyteshortintCharacterByteShortIntegerStringまたはenum型ではないか、(ii)少なくとも1つのswitchラベルがパターンのcaseラベル要素またはnull caseラベル要素を持つかのいずれかです。

つまり、すべてのswitch文のswitchブロックに対して次のすべてが当てはまる必要があり、そうでない場合はコンパイル時にエラーが発生します。

Java SE 17より前は、switch文(およびswitch式)は2通りに制限されていました: (i)セレクタ式の型は、整数型、enum型またはStringに制限されていました。(ii)定数のcaseラベル要素のみがサポートされていました。さらに、switch式とは異なり、switch文は網羅的である必要はありませんでした。これは多くの場合、バグの検出を困難にする原因になり、switchラベルは適用されず、switch文は何もしません。たとえば:

enum E { A, B, C}

E e = ...;
switch (e) {
   case A -> System.out.println("A");
   case B -> System.out.println("B");
   // No case for C!
}

Java SE 17では、前述の2つの制限を取り除くという意味でswitch文が拡張されました。Javaプログラミング言語の設計者が、拡張switch文はswitch式と揃える必要があり、網羅的である必要があると決めました。これは多くの場合、自明なデフォルトswitchラベルの追加で達成されます。たとえば、次の拡張switch文は網羅的ではありません。

Object o = ...;
switch (o) {    // Error - non-exhaustive switch!
    case String s -> System.out.println("A string!");
}

しかし、それは簡単に網羅的にすることができます。

Object o = ...;
switch (o) {    
    case String s -> System.out.println("A string!");
    default -> {}
}

互換性の理由で、拡張switch文ではないswitch文は網羅的である必要はありません。

14.11.3 switch文の実行

switch文の実行は常に、解決されたswitchブロックに関連します(14.11.1)。switchブロックは型Tで解決され、ここでTはセレクタ式の型です。

switch文は、最初にセレクタ式を評価することで実行されます。次に、

セレクタ式の評価が正常に完了する場合、結果が非nullで後続のボックス化解除変換(ある場合)が正常に完了するとき、switch文の実行は、解決されたswitchブロックに関連付けられた内のswitchラベルがセレクタ式の値と一致するに適用されるかどうかを決定することで続行されます(14.11.1)。次に、

switchブロックの文または式の実行が突然完了する場合、次のように処理されます。

例14.11.3-1.switch文のフォールスルー

セレクタ式がswitchラベルに一致しswitchラベルが適用され、そのswitchラベルがswitchルールに対するものである場合、switchラベルによって導入されたswitchルール式または文が実行されるのみです。文グループ用のswitchラベルの場合、そのswitchラベルに続くswitchブロックのすべてのブロック文が、後続のswitchラベルの後に出現するものを含めて実行されます。その効果は、CおよびC++でのように、文の実行が「ラベルをフォールスルー」できることです。

たとえば、次のプログラムの場合:

class TooMany {
    static void howMany(int k) {
        switch (k) {
            case 1: System.out.print("one ");
            case 2: System.out.print("too ");
            case 3: System.out.println("many");
        }
    }
    public static void main(String[] args) {
        howMany(3);
        howMany(2);
        howMany(1);
    }
}

caseのコードが次のcaseのコードにフォールスルーするswitchブロックを含みます。結果として、プログラムの出力は次のようになります。

many
too many
one too many

フォールスルーは判断しにくいバグの原因になる場合があります。コードがこのようにcaseからcaseにフォールスルーする予定ではない場合、break文を使用して、いつ制御を転送する必要があるかを示すことができます。または、switchルールを次のプログラムのように使用できます。

class TwoMany {
    static void howMany(int k) {
        switch (k) {
            case 1: System.out.println("one");
                    break;  // exit the switch
            case 2: System.out.println("two");
                    break;  // exit the switch
            case 3: System.out.println("many");
                    break;  // not needed, but good style
        }
    }
    static void howManyAgain(int k) {
        switch (k) {
            case 1 -> System.out.println("one");
            case 2 -> System.out.println("two");
            case 3 -> System.out.println("many");
        }
    }
    public static void main(String[] args) {
        howMany(1);
        howMany(2);
        howMany(3);
        howManyAgain(1);
        howManyAgain(2);
        howManyAgain(3);    
    }
}

このプログラムは次を出力します。

one
two
many
one
two
many

14.30 パターン

パターンは、値に対して実行できるテストを示します。パターンは文および式のオペランドとして出現し、テストする値を提供します。パターンはパターン変数として知られるローカル変数を宣言します。

パターンに対して値をテストするプロセスはパターン・マッチングと呼ばれます。値がパターンに正常に一致する場合、パターン・マッチングのプロセスが、パターンによって宣言されたパターン変数を初期化します。

パターン変数は、パターン・マッチングが成功するスコープ(6.3)内にのみあるため、パターン変数が初期化されています。初期化されていないパターン変数を使用することはできません。

14.30.1 パターンの種類

プライマリ・パターンはパターンの最も単純な形であり、そこから他のすべてが構成されます。型パターンは、値がパターンに出現する型のインスタンスであるかどうかをテストするために使用されます。カッコ付きのパターンは、構文的にプライマリ・パターンとしても扱われます。

ガード付きパターンは、含まれたプライマリ・パターンおよび含まれたガーディング式で構成され、値がパターンと一致するかどうか、さらに、ガーディング・ブール式がtrueであるかどうかをテストするために使用されます。

Pattern:
TypePattern
Pattern:
PrimaryPattern
GuardedPattern
GuardedPattern:
PrimaryPattern && ConditionalAndExpression
PrimaryPattern:
TypePattern
( Pattern )
TypePattern:
LocalVariableDeclaration

便宜上、ここでは4.38.38.4.1、および14.4の次のプロダクションを示します。

LocalVariableDeclaration:
{VariableModifier} LocalVariableType VariableDeclaratorList
VariableModifier:
Annotation
final
LocalVariableType:
UnannType
var
VariableDeclaratorList:
VariableDeclarator {, VariableDeclarator}
VariableDeclarator:
VariableDeclaratorId [= VariableInitializer]
VariableDeclaratorId:
Identifier [Dims]
Dims:
{Annotation} [ ] {{Annotation} [ ]}

UnannTypeについては、8.3を参照してください。

特殊なanyパターンもあります。これは、パターンの解決のプロセスから発生するパターンです(14.30.2)。

現在、anyパターンは、パターンinstanceof式、またはswitch式またはswitch文のパターン・ラベルには出現できません。Javaプログラミング言語の将来のバージョンで、この制限が緩和される可能性があります。

型パターンは、パターン変数として知られる1つのローカル変数を宣言します。ローカル変数宣言の識別子は、パターン変数の名前を指定します。

型パターンで宣言されたローカル変数のルールについては、14.4に規定されています。さらに、次のすべてが当てはまる必要があり、そうでない場合、コンパイル時にエラーが発生します。

パターン変数の型は、LocalVariableTypeによって示された参照型です。

型パターンの型は、そのパターン変数の型です。

カッコ付きのパターンは、含まれたパターンによって宣言されたローカル変数を宣言します。

カッコ付きのパターンの型は、含まれたパターンの型です。

anyパターンは、パターン変数として知られる1つのローカル変数を宣言します。

anyパターンのパターン変数は、参照型である型を持ちます。

anyパターンの型は、そのパターン変数の型です。

次のいずれかが当てはまる場合、パターン変数はガード・パターンp&&eによって宣言されます。

パターン変数のいずれかが、含まれたパターンによって宣言され、当てはまる場合にガード付きパターンのガーディング式によっても宣言される場合、コンパイル時にエラーになります。

使用されているが、ガード付きパターンのガーディング式で宣言されていない変数は、finalまたは事実上のfinal (4.12.4)のいずれかである必要があります。

ガード付きのパターンの型は、含まれたパターンの型です。

eは、eTとダウンキャスト互換性がある場合、型Tのパターンと互換性があります(5.5)。

eは、次のいずれかが当てはまる場合、パターンと互換性があります

式のパターンとの互換性は、instanceofパターン一致演算子(15.20.2)、およびswitchラベル内のパターンを使用しているswitch式またはswitch文(14.11.1)によって使用されます。

14.30.2 パターン・マッチング

パターン・マッチングは、実行時にパターンに対して値をテストするプロセスです。パターン・マッチングは、文実行(14.1)および式評価(15.1)とは異なります。

パターン・マッチングが実行される前に、パターンはまず、照合される式の型に関して解決され、修正された可能性があるパターンになります。

Uでのパターンの解決のルールは、次のとおりです。

パターンの解決のこのプロセスは、型パターンに対してnull参照値を照合したときに発生する問題に対処します。値が型Uの型パターンと一致するかどうかのチェックには、値をUにキャストできるかどうかの(実行時の)チェックが含まれます。しかし、null参照はチェックなしで任意の参照型にキャストできます。それでも、型Vの式が最終的にnull参照に評価される場合、Vが型パターンの型のサブタイプであった場合のみ照合が成功すると期待します。

これは、パターン・マッチングがコンパイル時型を含む必要があることを示します。コンパイル時型に関してパターン・マッチングの実行時プロセスを直接定義するのではなく、パターン・マッチングが次のプロパティを満たす必要があります。静的型がTである任意の式の値は常に、TSのサブタイプである型Sの型パターンと一致します。

このように、コンパイル時に、パターン・マッチングされる式の(コンパイル時)型に関してパターンを解決します。パターンが常に一致するとコンパイル時に判断できる場合、それは、特別なanyパターン(実行時型の調査なしで、定義によってすべての値が一致します)に変換または解決されます。これにより、照合する値がnull参照である場合に、期待した動作が確実に行われます。その他の場合、パターンの解決によってパターンがそのままの状態になります。

一部のパターンには、パターン・マッチング中に評価される式が含まれます。含まれている式の評価が突然完了する場合、パターン・マッチングは突然完了すると言い表されます。突然の完了には常に理由が関連付けられており、それは常に、指定された値を持つthrowです。パターン・マッチングは、突然完了しない場合、正常に完了すると言い表されます。

値がパターンと一致するかどうかを決定するルールおよびパターン変数を初期化するルールは、次のとおりです。

null参照である値を対象とするルールはありません。これは、パターン・マッチングを実行する単独のコンストラクトであるinstanceofパターン一致演算子(15.20.2)が、値がnull参照ではない場合にのみパターン・マッチングを実行するためです。Javaプログラミング言語の将来のバージョンで、他の式および文でのパターン・マッチングが許可される可能性があります。

14.30.3 パターン全域性および優位性

次のように、パターンは型T合計であると言い表されます。

qと一致するすべての値がpとも一致する場合、パターンpはパターンqより優先されると言い表され、次のように定義されています。

第15章: 式

15.20 関係演算子

15.20.2 instanceof演算子

instanceof式は型比較またはパターン・マッチングのいずれかを実行できます。

InstanceofExpression:
RelationalExpression instanceof ReferenceType
RelationalExpression instanceof Pattern PrimaryPattern

instanceofキーワードの右側のオペランドがReferenceTypeである場合、instanceofキーワードは型比較演算子です。

instanceofキーワードの右側のオペランドがPatternである場合、instanceofキーワードはパターン一致演算子です。

次のルールは、instanceofが型比較演算子の場合に適用されます。

次のルールは、instanceofがパターン一致演算子の場合に適用されます。

例15.20.2-1.型比較演算子

class Point   { int x, y; }
class Element { int atomicNumber; }
class Test {
    public static void main(String[] args) {
        Point   p = new Point();
        Element e = new Element();
        if (e instanceof Point) {  // compile-time error
            System.out.println("I get your point!");
            p = (Point)e;  // compile-time error
        }
    }
}

このプログラムの結果、コンパイル時に2つのエラーが発生します。Elementまたは使用可能なそのサブクラス(ここには示されていません)のインスタンスがPointのサブクラスのインスタンスではない可能性があるため、キャスト(Point)eは正しくありません。まったく同じ理由により、instanceof式も正しくありません。一方、クラスPointElementのサブクラスであった場合(この例では明らかに奇妙な表記です):

class Point extends Element { int x, y; }

キャストは可能になりますが、実行時のチェックが必要になるため、instanceof式が実用的かつ有効です。キャスト(Point)eは、eの値を型Pointに正確にキャストできない場合には実行されないため、これによって例外が呼び出されることはありません。

Java SE 16より前は、reifiableにするには型比較演算子のReferenceTypeオペランドが必要でした(4.7)。これにより、そのすべての型引数がワイルドカードでないかぎり、パラメータ化型を使用できませんでした。多くのパラメータ化型の使用を許可するために、その要件はJava SE 16で取り除かれました。たとえば、次のプログラムで、静的型List<Integer>のあるメソッド・パラメータxに、さらに詳細なパラメータ化型ArrayList<Integer>があるかどうかを実行時にテストすることは有効です。

import java.util.ArrayList;
import java.util.List;

class Test2 {
    public static void main(String[] args) {
        List<Integer> x = new ArrayList<Integer>();
    
        if (x instanceof ArrayList<Integer>) {  // OK
            System.out.println("ArrayList of Integers");
        }
        if (x instanceof ArrayList<String>) {  // error
            System.out.println("ArrayList of Strings");
        }
        if (x instanceof ArrayList<Object>) {  // error
            System.out.println("ArrayList of Objects");
        }
    }
}

最初のinstanceof式は、List<Integer>からArrayList<Integer>へのキャスト変換があるため有効です。ただし、2番目および3番目のinstanceof式では、List<Integer>からArrayList<String>またはArrayList<Object>へのキャスティング変換がないため、どちらもコンパイル時にエラーが発生します。

15.28 switch

switch式は、式の値に応じて、いくつかの文または式の1つに制御を転送します。その式のすべての可能な値が処理される必要があり、いくつかの文または式のすべてがswitch式の結果の値を生成する必要があります。

SwitchExpression:
switch ( Expression ) SwitchBlock

Expressionセレクタ式と呼ばれます。セレクタ式の型はcharbyteshortintCharacterByteShortIntegerStringまたはenum型(8.9)である必要があり、そうでない場合、コンパイル時にエラーが発生します。

switch式およびswitch文(14.11)の両方の本体は、switchブロックと呼ばれます。switch式またはswitch文のどちらに出現するかに関係なく、すべてのswitchブロックに適用される一般的なルールは、14.11.1に示されています。便宜上、ここでは14.11.1の次のプロダクションを示します。

SwitchBlock:
{ SwitchRule {SwitchRule} }
{ {SwitchBlockStatementGroup} {SwitchLabel :} }
SwitchRule:
SwitchLabel -> Expression ;
SwitchLabel -> Block
SwitchLabel -> ThrowStatement
SwitchBlockStatementGroup:
SwitchLabel : {SwitchLabel :} BlockStatements
SwitchLabel:
case CaseConstant {, CaseConstant}
default
SwitchLabel:
CaseOrDefaultLabel {: CaseOrDefaultLabel }
CaseOrDefaultLabel:
case CaseLabelElement {, CaseLabelElement }
default
CaseLabelElement:
CaseConstant
Pattern
null
default
CaseConstant:
ConditionalExpression

15.28.1 switch式のSwitchブロック

switchブロック(14.11.1)の一般的なルールに加えて、switch式のswitchブロックにはさらにルールがあります。つまり、switch式のswitchブロックに対して次のすべてが当てはまる必要があり、そうでない場合はコンパイル時にエラーが発生します。

switch式は、switch文とは異なり、空のswitchブロックを持つことができません。さらに、switch式は、switchブロックの矢印(->)の右にどの式が出現するか、つまり、どの式をswitchルール式として使用できるかという観点で、switch文と異なります。switch式では、任意の式をswitchルール式として使用できますが、switch文では、文の式のみを使用できます(14.11.1)。

switch式は網羅的である必要があり(14.11.1)、そうでない場合、コンパイル時にエラーが発生します。

switch式の結果式は、次のように決定されます。

switch式に結果式がない場合、コンパイル時にエラーになります。

switch式が割当てコンテキストまたは呼出しコンテキスト(5.25.3)に出現する場合、それは複合式です。それ以外の場合はスタンドアロン式です。

複合switch式がターゲット型Tの特定の種類のコンテキストに出現する場合、その結果式も同様にターゲット型Tの同じ種類のコンテキストに出現します。

複合switch式は、その結果式のそれぞれがTと互換性がある場合、ターゲット型Tと互換性があります。

複合switch式の型は、そのターゲット型と同じです。

スタンドアロンswitch式の型は、次のように決定されます。

15.28.2 switch式の実行時評価

switch式の評価は常に、解決されたswitchブロックに関連します(14.11.1)。switchブロックは型Tで解決され、ここでTはセレクタ式の型です。

switch式は、最初にセレクタ式を評価することで評価されます。次に、

セレクタ式の評価が正常に完了する場合、結果が非nullで後続のボックス化解除変換(ある場合)が正常に完了するとき、switch式の評価は、解決されたswitchブロックに関連付けられた内のswitchラベルがセレクタ式の値と一致するに適用されるかどうかを決定することで続行されます(14.11.1)。次に、

switchブロックの文または式の実行が突然完了する場合、次のように処理されます。

第16章: 明確な割当て

16.2 明確な割当ておよび文

16.2.9 switch