第16章 確定割当

目次

16.1 確定割当および式
16.1 ブール定数式
16.1 条件付き演算子&&
16.1 条件付きまたは演算子||
16.1 論理補完演算子!
16.1 条件演算子? :
16.1.6. switch
16.1 boolean型のその他の式
16.1 割当式
16.1 演算子++および--
16.1 その他の式
16.2 明確な割当てと文
16.2 空の文
16.2 ブロック
16.2 ローカルクラスとインタフェース宣言
16.2 ローカル変数宣言文
16.2 ラベル付き文
16.2 式文
16.2.7. if
16.2.8. assert
16.2.9. switch
16.2.10. while
16.2.11. do
16.2.12. for
16.2.12.1. for文の初期化部分
16.2.12.2. for文の増分部分
16.2.13. breakyieldcontinuereturnおよびthrow
16.2.14. synchronized
16.2.15. try
16.3 確定割当およびパラメータ
16.4 確定割当および配列初期化子
16.5 確定割当て定数と列挙定数
16.6 確定割当および匿名クラス
16.7 確定割当とメンバー・クラスおよびインタフェース
16.8 確定割当および静的イニシャライザ
16.9 確定割当て、コンストラクタおよびインスタンス初期化子

文(§14.4.2§14.14.1§14.14.2§14.20.3)および空白のfinalフィールド(§4.12.4§8.3.1.2)によって宣言されたすべてのローカル変数には、その値へのアクセスが発生したときに絶対的に割り当てられる値が必要です。

その値へのアクセスは、単純代入演算子= (§15.26.1)の左オペランドを除き、式内の任意の場所で発生する変数の単純名(またはフィールドの場合、thisで修飾されるフィールドの単純名)で構成されます。

xまたは空白のfinalフィールドxによって宣言されたローカル変数のすべてのアクセスについて、アクセス前にxを必ず割り当てる必要があります。そうしないと、コンパイル時にエラーが発生します。

同様に、すべての空白のfinal変数は、最大で1回割り当てる必要があります。割り当てが発生した場合は、無期限に割当て解除する必要があります。

このような代入は、変数の単純名(またはフィールドの場合はthisで修飾された単純名)が代入演算子の左側に存在する場合にのみ、発生するように定義されます。

空白のfinal変数への割当てごとに、割当ての前に変数を割当て解除する必要があります。そうしないと、コンパイル時にエラーが発生します。

同様に、クラスCのコンストラクタで発生する代替コンストラクタ呼出し(§8.8.7.1)ごとに、Cで宣言されたCのすべての空白のfinalインスタンス変数は、代替コンストラクタ呼出しの引数リストの後に必ず割当て解除する必要があります。そうしないと、コンパイル時にエラーが発生します。

パターン(§14.30)で宣言された局所変数は、明確な代入の規則の対象ではないことに注意してください。 パターンで宣言されたすべてのローカル変数は、パターン・マッチングのプロセスで初期化されるため、アクセス時には常に値を持っています。

この章の残りの部分では、「前に明確に割り当てる」および「前に明確に割当て解除する」という語句について正確に説明します。

明確な割当ての背後にある考え方は、文または空白のfinalフィールドによって宣言されたローカル変数への割当てが、アクセスに対して可能なすべての実行パスで発生する必要があることです。 同様に、明確な割当て解除の背後にある考え方は、割当てへの可能な実行パスに対して、空白のfinal変数への他の割当ては実行できないことです。

分析では文と式の構造が考慮され、式演算子&&||!および? :とブール値定数式の特別な処理も提供されます。

条件付きブール演算子&&||および? :およびブール値定数式の特別な処理を除き、式の値はフロー分析では考慮されません。

例16-1. 定義割当ては文と式の構造を考慮します。

Javaコンパイラは、kがコード内のアクセス前に(メソッド呼出しの引数として)確実に割り当てられていることを認識します。


{
    int k;
    if (v > 0 && (k = System.in.read()) >= 0)
        System.out.println(k);
}

これは、式の値の場合にのみアクセスが発生するためです。


v > 0 && (k = System.in.read()) >= 0

trueで、kへの割当てが実行される(より適切に評価される)場合にのみ、値をtrueにできます。

同様に、Javaコンパイラはコード内で次のことを認識します。


{
    int k;
    while (true) {
        k = n;
        if (k >= 5) break;
        n = 6;
    }
    System.out.println(k);
}

条件式trueは値falseを持たないため、while文によって変数kが確実に割り当てられます。そのため、break文のみがwhile文が正常に完了し、break文の前にkが確実に割り当てられます。

一方、コードは次のようになります。


{
    int k;
    while (n < 4) {
        k = n;
        if (k >= 5) break;
        n = 6;
    }
    System.out.println(k);  /* k is not "definitely assigned"
                               before this statement */
}

この場合、while文は、定義済割当てのルールに関するかぎり本文の実行が保証されないため、Javaコンパイラによって拒否される必要があります。


例16-2. 定義割当てでは式の値は考慮されません

Javaコンパイラは、次のコードに対してコンパイル時エラーを生成する必要があります。


{
    int k;
    int n = 5;
    if (n > 2)
        k = 3;
    System.out.println(k);  /* k is not "definitely assigned"
                               before this statement */
}

nの値はコンパイル時に認識されていても、原則として、kへの割当てが常に実行される(より適切に評価される)ことをコンパイル時に認識できます。 Javaコンパイラは、この項で説明するルールに従って動作する必要があります。 ルールは定数式のみを認識します。この例では、式n > 2§15.29で定義されている定数式ではありません。

別の例として、Javaコンパイラは次のコードを受け入れます。


void flow(boolean flag) {
    int k;
    if (flag)
        k = 3;
    else
        k = 4;
    System.out.println(k);
}

kの明確な割当てに関しては、この項で説明するルールによって、flagtruefalseかに関係なく、kが割り当てられていることが示されるためです。 しかし、ルールは次のバリエーションを受け入れません。


void flow(boolean flag) {
    int k;
    if (flag)
        k = 3;
    if (!flag)
        k = 4;
    System.out.println(k);  /* k is not "definitely assigned"
                               before this statement */
}

したがって、このプログラムをコンパイルすると、コンパイル時にエラーが発生します。


例16-3. 確定未割当

Javaコンパイラは、次のコードを受け入れます。


void unflow(boolean flag) {
    final int k;
    if (flag) {
        k = 3;
        System.out.println(k);
    }
    else {
        k = 4;
        System.out.println(k);
    }
}

kの明確な割当て解除に関しては、この項で説明するルールを使用すると、flagtruefalseかに関係なく、kが最大で1回(実際は1回)割り当てられることを通知できます。 しかし、ルールは次のバリエーションを受け入れません。


void unflow(boolean flag) {
    final int k;
    if (flag) {
        k = 3;
        System.out.println(k);
    }
    if (!flag) {
        k = 4;
        System.out.println(k);  /* k is not "definitely unassigned"
                                   before this statement */
    }
}

したがって、このプログラムをコンパイルすると、コンパイル時にエラーが発生します。


明確な割当てのすべてのケースを正確に指定するために、この項のルールではいくつかの技術用語を定義します。

ブール値式の場合、最後の2つは4つのケースに絞り込まれます。

ここでは、when trueおよびwhen falseが式の値を参照しています。

たとえば、ローカル変数kには、式の評価後に必ず値が割り当てられます。


a && ((k=m) > 5)

式がtrueで、式がfalseの場合ではない場合(aがfalseの場合、kへの割当てが必ずしも実行されるとはかぎりません(より適切に評価されます)。

V」という語句は、Xのあとに必ず割り当てられます(ここで、Vはローカル変数で、Xはステートメントまたは式です)は、「Xが正常に完了した場合、VXのあとに必ず割り当てられます」を意味します。 Xが突然完了した場合、割り当ては発生する必要はなく、ここで説明する規則ではこのことが考慮されます。

この定義の特有の結果は、「Vは必ず break;のあとに割り当てられます」が常に真であることです。 break文が正常に完了することはないため、break文が正常に完了した場合、Vに値が割り当てられていることは事実です。

ステートメント"V is sure unassigned after X" (ここで、V is a variable and X is a statement or expression)は、"V is sure unassigned after X if X complete normal."を意味します。

この定義のさらに特殊な結果は、「Vbreak;のあとに絶対に割り当てられません」が常に真であることです。 break文が正常に完了することはないため、break文が正常に完了した場合、Vに値が割り当てられていないことは事実です。 (この問題については、break文が正常に完了した場合、月は緑色のチーズでできていることも事実です。)

文または式の実行後に、変数 Vに次の4つの可能性が考えられます。

ルールを短縮するために、慣習的な略称「iff」は「if and only if」を意味するために使用されます。 また、略称規則も使用します。ルールに「[un]assigned」の出現が1つ以上含まれる場合、2つのルールを表します。1つは「[un]assigned」の出現ごとに「definitely assigned」に置換され、もう1つは「[un]assigned」の出現ごとに「definitely unassigned」に置換されます。

たとえば:

  • 空のステートメントの前に Vが[un]割り当てられている場合は、空のステートメントのあとに Vが割り当てられます。

次の2つのルールに従うことを理解する必要があります。

  • Vは、空のステートメントiffのあとに、必ず空のステートメントの前に割り当てられます。

  • 空のステートメントiffのあとに Vが必ず割り当て解除され、空のステートメントの前に割り当てられます。

この章の内容全体を通して、特に明記しないかぎり、Vを記述して、文によって宣言されたローカル変数、またはスコープ内の空白のfinalフィールド(§6.3)を表します。 同様に、式を表すにはabcおよびeを使用し、文を表すにはSおよびTを使用します。 "a is V"という語句を使用して、aが変数Vの単純名、またはthisで修飾されたVの単純名(カッコを無視)であることを意味します。 a is not V」という語句は、「a is V」の否定を表すために使用します。

ループ文の明確な割当て解除分析では、特別な問題が発生します。 while (e) S文について考えてみます。 eの一部のサブ式内でVが確実に割当て解除されるかどうかを判断するには、eの前にVが確実に割当て解除されるかどうかを判断する必要があります。 確定割当てのルール(§16.2.10)と類似しているため、Ve iffの前に必ず割当て解除され、while文の前に割当て解除されます。 しかし、そのような規則は我々の目的にとって不十分である。 etrueと評価されると、文Sが実行されます。 後で、VSによって割り当てられている場合、eの評価時に次の反復 Vがすでに割り当てられています。 前述のルールでは、Vを複数回割り当てることが可能です。これは、これらのルールを導入することで回避しようとしたものです。

改訂されたルールは、"Vは、while文の前に確実に割当て解除され、Sの後に確実に割当て解除される場合は、eの前に確実に割当て解除されます。"です。 ただし、Sのルールを定式化すると、「VSの前に絶対に割り当て解除されます(trueの場合、eのあとに確実に割り当て解除される場合)。 これは循環につながります。 Vは、ループ全体のに割当て解除されている場合にのみ、ループ条件eに割当て解除されます。

この悪循環は、ループ状態と本体の仮説的な分析を使用して破ります。 たとえば、Vが(Vが実際に eより前に割り当てられていないかどうかに関係なく) eより前に確実に割り当てられていないと仮定し、Veのあとに確実に割り当て解除されたことを証明できる場合、eVを割り当てないことがわかります。 これは、より正式に次のように記載されています。

eの前に Vの割り当てが確実に解除されていると仮定すると、Veのあとに確実に割り当て解除されます。

前述の分析のバリエーションは、Javaプログラミング言語のすべてのループ文に対して明確に定義された割当て解除ルールを定義するために使用されます。

16.1. 確定割当および式

16.1.1. ブール定数式

  • Vは、falseの場合、値がtrueである定数式(§15.29)の後に[un]割り当てられます。

  • Vは、trueの場合に値がfalseの定数式の後に割り当てられます。

  • 定数式の前に Vが[un]割り当てられている場合、真であれば値が trueである定数式のあとに Vが割り当てられます。

  • 定数式の前に Vが[un]割り当てられている場合は、Vfalseである定数式のあとに Vが割り当てられます。

  • trueの場合、Veの後に[un]割り当てられ、falseの場合、Veの後に[un]割り当てられると、Vはブール値の定数式eの後に[un]割り当てられます。

    これは、Veの前に割り当てられている場合、eのあとに Vが[un]割り当てられているということと同等です。

値がtrueの定数式には値falseは含まれず、値がfalseの定数式には値trueは含まれないため、最初の2つのルールは空に満たされます。 これらは、演算子&& (§16.1.2)、|| (§16.1.3)、! (§16.1.4)および? : (§16.1.5)を含む式の分析に役立ちます。

16.1.2. 条件付き演算子&&

  • trueの場合、Va && b (§15.23)の後に[un]割り当てられます(trueの場合、Vbの後に[un]割り当てられます)。

  • falseの場合、Va && bのあとに割り当てられず、falseの場合、Vaのあとに割り当てられず、Vbのあとに割り当てられません。

  • Va && bの前に割り当てられると、Vaの前に割り当てられます。

  • trueの場合、Vaの後に割り当てられると、Vbの前に[un]割り当てられます。

  • trueの場合、Va && bの後に[un]割り当てられ、falseの場合、Va && bの後に[un]割り当てられると、Va && bの後に割り当てられます。

16.1.3. 条件付きまたは演算子||

  • trueの場合はa || b (§15.24)の後にVが[un]割り当てられ、trueの場合はVaの後に[un]割り当てられ、trueの場合はVbの後に[un]割り当てられます。

  • falseの場合、Va || bの後に[un]割り当てられます(falseの場合、Vbの後に[un]割り当てられます)。

  • Va || bの前に割り当てられると、Vaの前に割り当てられます。

  • Vが偽の場合、Vaのあとに割り当てられると、Vbの前に割り当てられます。

  • trueの場合、Va || bの後に[un]割り当てられ、falseの場合、Va || bの後に[un]割り当てられると、Va || bの後に割り当てられます。

16.1.4. 論理補完演算子!

  • falseの場合、Vaの後に[un]割り当てられている場合は、trueの場合、V!a (§15.15.6)の後に[un]割り当てられます。

  • trueの場合、Vaの後に[un]割り当てられると、falseの場合、V!aの後に[un]割り当てられます。

  • V!aの前に割り当てられている場合、Vaの前に割り当てられません。

  • trueの場合、V!aの後に[un]割り当てられ、falseの場合、V!aの後に[un]割り当てられると、V!aの後に割り当てられます。

    これは、Vaのあとに割り当てられている場合、V!aのあとに割り当てられると[un]と同等です。

16.1.5. 条件演算子? :

bおよびcがブール値式であるとします。

  • trueの場合、Vbの後に[un]割り当てられ、trueの場合はVcの後に[un]割り当てられ、trueの場合はVa ? b : cの後に[un]割り当てられます(§15.25)。

  • a ? b : cのあとに Vが割り当てられるのは、falseの場合は bのあとに Vが割り当てられ、falseの場合は cのあとに Vが割り当てられるのは[un]です。

  • Va ? b : cの前に[un]割り当てられている場合、Vaの前に[un]割り当てられます。

  • trueの場合、Vaの後に割り当てられると、Vbの前に[un]割り当てられます。

  • Vが偽の場合、Vaのあとに割り当てられると、Vcの前に割り当てられます。

  • trueの場合はa ? b : cの後にVが割り当てられ、falseの場合はVa ? b : cの後に割り当てられ、Va ? b : cの後に割り当てられる場合は[un]が割り当てられます。

bおよびcがブール値でない式であるとします。

  • Vbのあとに割り当てられ、Vcのあとに割り当てられると、Va ? b : cのあとに割り当てられます。

  • Va ? b : cの前に[un]割り当てられている場合、Vaの前に[un]割り当てられます。

  • trueの場合、Vaの後に割り当てられると、Vbの前に[un]割り当てられます。

  • Vが偽の場合、Vaのあとに割り当てられると、Vcの前に割り当てられます。

16.1.6. switch

switch式(§15.28)に結果式e1、...、enがあり、そのすべてがブール値であるとします。

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

  • switch式を終了する可能性のあるswitchブロック内の式e (§14.21)を持つすべてのyield文についてtrue iffの場合、Vswitch式の後に確実に割り当てられ、trueの場合、Veの後に確実に割り当てられます。

  • Vは、switch式を終了する可能性のあるswitchブロック内の式eを持つすべてのyield文に対してfalse iffの場合、switch式の後に必ず割り当てられます。falseの場合、Veの後に必ず割り当てられます。

  • switch式を終了する可能性のあるswitchブロック内の式eを持つすべてのyield文について、Vは必ずswitch式の後に割当て解除され、trueの場合はVyield文の前に割当て解除され、Veの後に割当て解除されます。

  • switch式を終了する可能性のあるswitchブロック内の式eを持つすべてのyield文について、Vswitch式の後に必ず割当て解除され、Vyield文の前に割当て解除され、falseの場合はVeの後に割当て解除されます。

  • Vswitch式の前に割り当てられていない場合、Vはセレクタ式の前に割り当てられます。

  • Vがセレクタ式のあとに割り当てられていない場合、Vはswitchブロック内の最初のswitchラベル付きステートメントグループの最初のステートメントの前に割り当てられます。

  • Vは、最初のiff V以外のswitchラベル付きステートメントグループの最初のステートメントの前に[un]割り当てられ、Vは前のステートメントのあとに[un]割り当てられます。

次のルールは、switch式のswitchブロックがswitchルール(§14.11.1)で構成されている場合にのみ適用されます。

  • Vは、スイッチ・ルールごとにtrue iffの場合、switch式の後に必ず割り当てられます。次のいずれかがtrueです。

    • スイッチ・ルール式eが導入され、trueの場合、Veの後に確実に割り当てられます。

    • スイッチ・ルール・ブロックBが導入され、式eswitch式を終了する可能性があるBに含まれるすべてのyield文について、trueの場合、Vは必ずeの後に割り当てられます。

    • スイッチ・ルールのthrow文が導入されています。

  • Vは、スイッチ・ルールごとにfalse iffの場合、switch式の後に必ず割り当てられます。次のいずれかがtrueです。

    • スイッチ・ルール式eが導入され、falseの場合、Veの後に確実に割り当てられます。

    • スイッチ・ルール・ブロックBが導入され、式eswitch式を終了する可能性があるBに含まれるすべてのyield文について、Vはfalseの場合、eの後に必ず割り当てられます。

    • スイッチ・ルールのthrow文が導入されています。

  • Vは、スイッチ・ルールごとにtrue iffの場合、switch式の後に必ず割当て解除されます。次のいずれかがtrueです。

    • スイッチ・ルール式eが導入され、trueの場合、Veの後に確実に割当て解除されます。

    • スイッチ・ルール・ブロックBが導入され、switch式を終了する可能性のある式eを持つすべてのyield文について、Vyield文の前に確実に割当て解除され、trueの場合、Veの後に確実に割当て解除されます。

    • スイッチ・ルールのthrow文が導入されています。

  • Vは、スイッチ・ルールごとにfalse iffの場合、switch式の後に必ず割当て解除されます。次のいずれかがtrueです。

    • スイッチ・ルール式eが導入され、falseの場合、Veの後に確実に割当て解除されます。

    • switchルール・ブロックBが導入され、switch式を終了する可能性のある式eを含むすべてのyield文について、Vyield文の前に完全に割当て解除され、falseの場合、Veの後に確実に割当て解除されます。

    • スイッチ・ルールのthrow文が導入されています。

  • Vがセレクタ式の後に[un]割り当てられている場合、switchブロック内のswitchルール式またはswitchルール文の前にVが[un]割り当てられます。

switch式に結果式e1、...、enがあり、そのすべてがブール値であるとはかぎりません。

  • Vは、次のすべてに該当する場合、switch式の後に[un]割り当てられます。

    • Vは、switch式を終了する可能性のあるすべてのyield文の前に割り当てられます。

    • switchブロック内のswitchルールごとに、switchルールによって導入されたswitchルール式、switchルール・ブロックまたはswitchルールthrow文の後にVが割り当てられます。

  • Vswitch式の前に割り当てられていない場合、Vswitch式のセレクタ式の前に割り当てられます。

  • Vswitch式のセレクタ式の後に[un]割り当てられている場合、switchブロック内のswitchルールによって導入されたswitchルール式、switchルール・ブロックまたはswitchルールthrow文の前にVが割り当てられます。

  • 次の両方が当てはまる場合のみ、Vは、switchブロックのswitchラベルが付いた文グループの最初のブロック文の前で割当て[解除]されます。

    • Vは、switch式のセレクタ式の後に割り当てられます。

    • switchラベルが付いた文グループがswitchブロックで初めてではない場合、Vは、前述のswitchラベルが付いた文グループの最後のブロック文の後で割当て[解除]されます。

  • 前述のブロック文のあとに Vが[un]割り当てられている場合、Vはswitchブロック内のswitchラベル付きステートメントグループの最初のものではないブロックステートメントの前に割り当てられます。

次のルールは、すべてのswitch式に適用されます。

  • Vがセレクタ式の後に[un]割り当てられている場合、Vは、switch式のswitchブロックに関連付けられたガードの前に[un]割り当てられます。

16.1.7. boolean型のその他の式

eboolean型の式で、ブール定数式、論理補数式!a、条件式a && b、条件式a || bまたは条件式a ? b : cではないとします。

  • Veのあとに割り当てられていない場合は、trueの場合、Veのあとに割り当てられます。

  • Veのあとに割り当てられると、falseの場合、Veのあとに割り当てられません。

16.1.8. 割当式

代入式a = ba += ba -= ba *= ba /= ba %= ba <<= ba >>= ba >>>= ba &= ba |= bまたはa ^= b (§15.26)。

  • 次のいずれかの場合、Vは代入式のあとに必ず割り当てられます。

    • aV、または

    • Vは、bの後に必ず割り当てられます。

  • aVでなく、Vbの後に確実に割当て解除されている場合、Vは割当て式の後に割当て解除されます。

  • Vが代入式の前に[un]割り当てられている場合、Vaの前に[un]割り当てられます。

  • Vaのあとに割り当てられていない場合、Vbの前に割り当てられます。

aVで、Va &= bなどの複合割当ての前に確実に割り当てられていない場合、コンパイル時にエラーが発生します。 前述の明確な代入の最初のルールには、単純な代入だけでなく複合代入式でも「a is V」という除算が含まれているため、Vはコードの後半の時点で確実に割り当てられたとみなされます。 分割された「a is V」を含めると、プログラムが受け入れられるか、コンパイル時にエラーが発生するかに関するバイナリ決定には影響しませんが、コード内の異なる点の数が間違っていると見なされるため、実際にはエラー報告の品質を向上させることができます。 前述の明確な割当て解除の最初のルールに、結合"a is not V"を含める場合も同様です。

16.1.9. 演算子++および--

  • Vは、++a (§15.15.1)、--a (§15.15.2)、a++ (§15.14.2)またはa-- (§15.14.3) (aVの場合)またはVのいずれかがオペランド式の後に確実に割り当てられる後に割り当てられます。

  • aVでなく、Vがオペランド式のあとに割り当てられていない場合は、++a--aa++、または a--のあとに Vが必ず割り当て解除されます。

  • V++a--aa++またはa--の前に[un]割り当てられている場合、Vaの前に[un]割り当てられます。

16.1.10. その他の式

式がブール定数式ではなく、プリインクリメント式++a、プレデクリメント式--a、ポストインクリメント式a++、ポストデクリメント式a--、論理補完式!a、条件式a && b、条件式a || b、条件式a ? b : c、代入式またはラムダ式でない場合は、次のルールが適用されます。

  • 式に副式がない場合、式の前に Vが[un]割り当てられている場合は、式の後ろに Vが[un]割り当てられます。

    このケースは、リテラル、名前、this (修飾と非修飾の両方)、引数なしの修飾されていないクラス・インスタンス作成式、式を含まないイニシャライザを含む配列作成式、スーパークラス・フィールド・アクセス式、引数なしの修飾および型修飾メソッド呼出し式、引数なしのスーパークラス・メソッド呼出し式およびスーパークラスおよび型修飾メソッド参照式に適用されます。

  • 式に副式が含まれている場合、Vが右端の直下部分式のあとに割り当てられると、その式のあとに Vが[un]割り当てられます。

アサーションの背後には、メソッド呼出し式の後に変数Vが確実に割当て解除されることがわかっているという、微妙な推論があります。 呼び出されたメソッドが割当てを実行できるため、それ自体は、フェース値で修飾なしで取得され、そのようなアサーションが常にtrueであるとはかぎりません。 ただし、Javaプログラミング言語の目的上、明確な割当て解除の概念は空白のfinal変数にのみ適用されることに注意してください。 Vが空白のfinalローカル変数である場合、その宣言が属するメソッドのみがVへの割当てを実行できます。 Vが空白のfinalフィールドの場合、Vの宣言を含むクラスのコンストラクタまたはイニシャライザのみがVへの割当てを実行できます。メソッドではVへの割当てを実行できません。 最後に、明示的なコンストラクタ呼出し(§8.8.7.1)は特別に処理されます(§16.9)。構文的にはメソッド呼出しを含む式文と似ていますが、式文ではないため、この項のルールは明示的なコンストラクタ呼出しには適用されません。

式がラムダ式の場合は、次のルールが適用されます。

  • Vが式の前に割り当てられている場合は、式の後ろに Vが割り当てられません。

  • Vがラムダ式の前に確実に割り当てられている場合、Vは、ラムダ本体である式またはブロック(§15.27.2)の前に必ず割り当てられます。

    ラムダ本体の前にVを確実に割当て解除できるルールはありません。 これは設計によるものです。ラムダ本体の前に絶対に割り当てられなかった変数は、後で割り当てられる可能性があるため、本体の実行時に変数の割当てが解除されることを結論付けることはできません。

xの直接副式y(xがラムダ式でない場合)では、次のいずれかが当てはまる場合、Vyの前に割り当てられます。

  • yxの左端の直下部分正規表現で、Vxの前に割り当てられます。

  • yはバイナリ演算子の右側のオペランドで、Vは左側のオペランドの後に割り当てられます。

  • xは配列アクセスで、yはカッコ内の部分正規表現で、Vはカッコの前に部分正規表現の後に割り当てられます。

  • xはプライマリ・メソッド呼出し式で、yはメソッド呼出し式の最初の引数式で、Vはターゲット・オブジェクトを計算するプライマリ式の後に割り当てられます。

  • xは、メソッド呼出し式またはクラス・インスタンス作成式です。yは引数式ですが、最初の式ではありません。Vは、yの左側の引数式の後に割り当てられます。

  • xは修飾クラス・インスタンス作成式で、yはクラス・インスタンス作成式の最初の引数式で、Vは修飾オブジェクトを計算するプライマリ式の後に割り当てられます。

  • xは配列作成式です。yはディメンション式ですが、最初の式ではありません。Vは、yの左側のディメンション式の後に割り当てられます。

  • xは、配列イニシャライザを介して初期化される配列作成式で、yxの配列イニシャライザで、Vyの左側のディメンション式の後に割り当てられます。

16.2.  明確な割当ておよび文

16.2.1.  空の文

  • Vは、空のステートメント(§14.6)の前に割り当てられていない場合は、空のステートメント(§14.6)のあとに割り当てられます。

16.2.2. ブロック

  • 空白のfinalメンバー・フィールドVは、Vのスコープ内のメソッドの本体であり、Vのスコープ内で宣言されたクラスの宣言の前に、ブロック(§14.2)の前に確実に割り当てられます(さらに、絶対に割り当てられません)。

  • ステートメント Sによって宣言されたローカル変数 Vは、メソッドの本体であるブロック、インスタンスイニシャライザ、または Sを含む静的イニシャライザの前に、必ず割り当て解除されます(さらに、確実には割り当てられません)。

  • CVのスコープ内で宣言されたクラスとします。 この場合、VC宣言の前に確実に割り当てられている場合に、VCで宣言されたメソッド、インスタンスイニシャライザ、または静的イニシャライザの本体であるブロックの前に、Vが必ず割り当てられます。

    Cで宣言されたメソッド、インスタンス・イニシャライザまたは静的イニシャライザの本体であるブロックの前に、Vが確実に割当て解除されていると結論付けられるルールはありません。 Cで宣言されたメソッド、インスタンスイニシャライザ、または静的イニシャライザの本体であるブロックの前に Vが割り当てられていないことを非公式に結論付けることができますが、そのような規則を明示的に記述する必要はありません。

  • Vが空のブロックの前に割り当てられている場合、Vは空のブロックのあとに[un]割り当てられます。

  • Vがブロック内の最後のステートメントのあとに割り当てられていない場合、Vは空でないブロックのあとに割り当てられます。

  • Vがブロックの前に割り当てられていない場合、Vはブロックの最初のステートメントの前に割り当てられます。

  • Vがブロック内の Sの直前のステートメントの直後に割り当てられている場合、Vはブロックのほかのステートメント Sの前に割り当てられません。

Vは、次の場合にブロックB内のどこでも確実に割当て解除されます:

  • VBの前に確実に割当て解除されている。

  • V is definitely assigned after e in every assignment expression V = e, V += e, V -= e, V *= e, V /= e, V %= e, V <<= e, V >>= e, V >>>= e, V &= e, V |= e, or V ^= e that occurs in B.

  • Vは、Bで発生するすべての式++V--VV++またはV--の前に必ず割り当てられます。

これらの条件は直感に反するもので、説明が必要です。 単純な割当てV = eについて考えてみます。 eの後にVが確実に割り当てられている場合は、次のいずれかを実行します。

  • 割当てはデッドコードで発生し、Vは無意味に確実に割り当てられている。 この場合、代入は実際には行われず、Vが代入式では割り当てられていないと想定できます。 または

  • Vは、eより前の式によってすでに割り当てられています。 この場合、現在の割当てによってコンパイル時にエラーが発生します。

そのため、コンパイル時にエラーが発生しないプログラムによって条件が満たされていると、BVへの割当ては実行時に実際には行われないと結論付けられます。

16.2.3.  ローカル・クラスおよびインタフェースの宣言

  • ローカルクラスまたはインタフェース宣言の前に Vが[un]割り当てられている場合、Vはローカルクラスまたはインタフェース宣言(§14.3)のあとに[un]割り当てられます。

16.2.4.  ローカル変数宣言文

  • Vがローカル変数宣言文の前に割り当てられていない場合、Vは変数イニシャライザを含まないローカル変数宣言文(§14.4.2)のあとに割り当てられます。

  • Vは、ローカル変数宣言文の最後の変数イニシャライザの後にVが確実に割り当てられている場合、または宣言の最後の変数イニシャライザがVを宣言する宣言子内に存在する場合、少なくとも1つの変数イニシャライザを含むローカル変数宣言文の後に確実に割り当てられます。

  • Vは、ローカル変数宣言文の最後の変数イニシャライザの後にVが確実に割当て解除され、宣言の最後の変数イニシャライザがVを宣言する宣言子内にない場合、少なくとも1つの変数イニシャライザを含むローカル変数宣言文の後に割当て解除されます。

  • ローカル変数宣言文の前に Vが[un]割り当てられている場合は、ローカル変数宣言文の最初の変数イニシャライザの前に Vが割り当てられます。

  • Vは、ローカル変数宣言文の最初の変数イニシャライザe以外の変数イニシャライザeの前に必ず割り当てられます(eの左側にある変数イニシャライザの後にVが確実に割り当てられるか、またはeの左側にあるイニシャライザ式がVを宣言する宣言子内にある場合)。

  • Vは、ローカル変数宣言文の最初の変数イニシャライザe以外の変数イニシャライザeの前に必ず割当て解除されます。ただし、Veの左側にある変数イニシャライザの後に確実に割当て解除され、eの左側にあるイニシャライザ式がVを宣言する宣言子内にない場合です。

16.2.5.  ラベルが付いた文

  • ラベル付きステートメント L : S (Lはラベル) (§14.7)のあとに、VSのあとに割り当てられ、Vがラベル付きステートメント L : Sを終了する可能性のあるすべての breakステートメントの前に割り当てられる[un]場合、Vは[un]になります。

  • VL : Sの前に割り当てられていない場合、VSの前に割り当てられます。

16.2.6. 式文

  • Vは、式文e; (§14.8) (eの後に割り当てられていない場合)の後に割り当てられます。

  • Ve;より前に割り当てられている場合は、eの前に割り当てられません。

16.2.7. if

if (e) S(§14.9.1)には、次のルールが適用されます。

  • VSのあとに[un]割り当てられ、Veのあとに(falseの場合)割り当てられると、Vif (e) Sのあとに[un]割り当てられます。

  • Vif (e) Sの前に割り当てられている場合、Veの前に割り当てられません。

  • trueの場合、Veの後に割り当てられると、VSの前に割り当てられません。

if (e) S else T(§14.9.2)には、次のルールが適用されます。

  • VSのあとに[un]割り当てられ、VTのあとに[un]割り当てられている場合、Vif (e) S else Tのあとに[un]割り当てられます。

  • Vif (e) S else Tの前に割り当てられている場合、Veの前に割り当てられません。

  • trueの場合、Veの後に割り当てられると、VSの前に割り当てられません。

  • Vが偽の場合、Veのあとに割り当てられると、VTの前に割り当てられます。

16.2.8. assert

次のルールは、文assert e1と文assert e1 : e2 (§14.10)の両方に適用されます。

  • Vassert文の前に[un]割り当てられている場合、Ve1の前に[un]割り当てられます。

  • Vassert文の前に確実に割り当てられている場合、Vassert文の後に必ず割り当てられます。

  • Vassert文の前に確実に割当て解除され、trueの場合はVe1の後に割当て解除された場合、Vassert文の後に割当て解除されます。

次のルールは、文assert e1 : e2に適用されます。

  • Vが偽の場合、Ve1のあとに割り当てられると、Ve2の前に割り当てられます。

16.2.9. switch

  • 次のすべてに該当する場合、Vswitch文(§14.11)の後に[un]割り当てられます。

    • Vは、switch文を終了する可能性のあるすべてのbreak文(§14.15)の前に割り当てられます。

    • switchブロックの各switchルール(§14.11.1)について、switchルールによって導入されたswitchルール式、switchルール・ブロックまたはswitchルールthrow文の後にVが割り当てられません。

    • switchブロックにswitchラベルが付いた文グループがある場合、Vは、最後のswitchラベルが付いた文グループの最後のブロック文の後で割当て[解除]されます。

    • switch文が完全ではない場合(§14.11.1.1)、またはswitchブロックがswitchラベルで終了し、その後に}セパレータが続く場合、Vはセレクタ式の後に割り当てられます。

  • Vswitch文の前に割り当てられていない場合、Vswitch文のセレクタ式の前に割り当てられます。

  • Vがセレクタ式の後に[un]割り当てられている場合、Vは、switch文のswitchブロックに関連付けられたガードの前に[un]割り当てられます。

  • switchルール式、switchルール・ブロックまたはswitchルールthrow文の前にVが割り当てられているのは、switch文のセレクタ式の後にVが割り当てられていない場合です。

  • 次の両方が当てはまる場合のみ、Vは、switchブロックのswitchラベルが付いた文グループの最初のブロック文の前で割当て[解除]されます。

    • Vは、switch文のセレクタ式の後に[un]割り当てられます。

    • switchラベルが付いた文グループがswitchブロックで初めてではない場合、Vは、前述のswitchラベルが付いた文グループの最後のブロック文の後で割当て[解除]されます。

  • 前述のブロック文のあとに Vが[un]割り当てられている場合、Vはswitchブロック内のswitchラベル付きステートメントグループの最初のものではないブロックステートメントの前に割り当てられます。

16.2.10. while

  • falseの場合、Veの後に[un]割り当てられ、while文がブレーク・ターゲットであるすべてのbreak文の前にVが[un]割り当てられている場合、Vwhile (e) S (§14.12)の後に[un]割り当てられます。

  • Vwhile文の前に確実に割り当てられている場合、Veの前に必ず割り当てられます。

  • 次のすべてに当てはまる場合、Vは必ず eの前に割り当てられません。

    • Vは、while文の前に必ず割当て解除されます。

    • Veの前に確実に割り当てられていないと仮定すると、VSのあとに確実に割り当て解除されます。

    • Veの前に確実に割当て解除されている場合、Vは、while文がcontinueターゲットであるすべてのcontinue文の前に確実に割当て解除されます。

  • trueの場合、Veの後に割り当てられると、VSの前に割り当てられません。

16.2.11. do

  • falseの場合、Veの後に[un]割り当てられ、do文がブレーク・ターゲットであるすべてのbreak文の前にVが[un]割り当てられている場合、Vdo S while (e); (§14.13)の後に[un]割り当てられます。

  • Vdo文の前に確実に割り当てられている場合、VSの前に必ず割り当てられます。

  • 次のすべてが当てはまる場合、VSの前に必ず割り当て解除されます。

    • Vは、do文の前に必ず割当て解除されます。

    • VSの前に確実に割り当てられていないと仮定すると、trueの場合、Veのあとに確実に割り当て解除されます。

  • VSの後に[un]割り当てられ、Vdo文がcontinueターゲットであるすべてのcontinue文の前に[un]割り当てられている場合、Veの前に[un]割り当てられます。

16.2.12. for

このルールは、基本的なfor文(§14.14.1)を対象としています。 拡張されたfor文(§14.14.2)は、基本的なfor文への変換によって定義されるため、特別なルールを指定する必要はありません。

  • 次の両方に該当する場合、Vfor文の後に[un]割り当てられます。

    • 条件式が存在しないか、falseの場合、Vが条件式のあとに割り当てられません。

    • Vは、for文がブレーク・ターゲットであるすべてのbreak文の前に割り当てられます。

  • Vfor文の前に割り当てられていない場合、Vfor文の初期化部分の前に割り当てられます。

  • Vfor文の初期化部分の後に確実に割り当てられている場合、Vfor文の条件部分の前に必ず割り当てられます。

  • Vは、次の両方に該当する場合、for文の条件部分の前に必ず割当て解除されます。

    • Vは、for文の初期化部分の後に必ず割当て解除されます。

    • for文の条件部分の前にVが確実に割当て解除されている場合、Vfor文の増分部分の後に割当て解除されます。

  • 次のいずれかが当てはまる場合、Vは含まれているステートメントの前に[un]割り当てられます。

    • 条件式が存在し、trueの場合、Vは条件式のあとに割り当てられます。

    • 条件式が存在せず、for文の条件部分の前にVが[un]割り当てられます。

  • Vが格納されている文の後に[un]割り当てられ、Vfor文がcontinueターゲットであるすべてのcontinue文の前に割り当てられると、Vfor文の増分部分の前に[un]割り当てられます。

16.2.12.1. for文の初期化部分

  • for文の初期化部分がローカル変数宣言文である場合、§16.2.4のルールが適用されます。

  • それ以外の場合、初期化パートが空の場合、Vが初期化パートの前に割り当てられていないと、Vは初期化パートのあとに割り当てられます。

  • それ以外の場合は、次の3つのルールが適用されます。

    • Vが初期化部分の最後の式文のあとに割り当てられている場合、Vは初期化部分の後で[un]割り当てられます。

    • 初期化部分の前に Vが[un]割り当てられている場合は、初期化部分の最初の式文の前に Vが割り当てられます。

    • VSの直前の式文のあとに[un]割り当てられている場合、Vは初期化部分の最初の式ステートメント S以外の式ステートメント Sの前に割り当てられます。

16.2.12.2. for文の増分部分

  • for文の増分部分が空の場合、増分部分の前にVが割り当てられていないと、Vは増分部分の後に割り当てられます。

  • それ以外の場合は、次の3つのルールが適用されます。

    • 増分部分の最後の式文のあとに Vが[un]割り当てられている場合、Vは増分部分のあとに[un]割り当てられます。

    • 増分部分の前に Vが[un]割り当てられている場合は、増分部分の最初の式文の前に Vが割り当てられます。

    • VSの直前の式文のあとに[un]割り当てられている場合、Vは増分部分の先頭以外の式ステートメント Sの前に割り当てられます。

16.2.13. breakyieldcontinuereturnおよびthrow

  • 慣例上、Vは、breakyieldcontinuereturn、または throw文(§14.15§14.21§14.16§14.17§14.18)のあとに[un]割り当てられると言います。

    変数がステートメントまたは式の後に「[un]assigned after」であるという概念は、実際には「is [un]assigned after the statement or expression completes.」を意味します。 break文、yield文、continue文、return文またはthrow文が正常に完了しないため、この概念を空欄で満たします。

  • 式がeyield文、式がereturn文、または式がethrow文では、Vyield文、return文またはthrow文の前に割り当てられている場合、Veの前に割り当てられません。

16.2.14. synchronized

  • VSの後に[un]割り当てられている場合、Vsynchronized (e) S (§14.19)の後に[un]割り当てられます。

  • Vが文synchronized (e) Sの前に[un]割り当てられている場合、Veの前に[un]割り当てられます。

  • Veのあとに割り当てられている場合、VSの前に割り当てられません。

16.2.15. try

本書の規則は、try-catch文およびtry-catch-finally文(§14.20.1§14.20.2)を対象としています。 try-with-resources文(§14.20.3)は、try-catch-finally文への変換によって定義されるため、特別なルールを指定する必要はありません。

これらのルールは、finallyブロックがあるかどうかに関係なく、すべてのtry文(§14.20)に適用されます。

  • Vtry文の前に割り当てられていない場合、Vtryブロックの前に割り当てられます。

  • Vtryブロックの前に確実に割り当てられている場合、Vcatchブロックの前に必ず割り当てられます。

  • Vは、次のすべてに該当する場合、catchブロックの前に必ず割当て解除されます。

    • Vは、tryブロックの後に必ず割当て解除されます。

    • Vは、tryブロックに属するすべてのreturn文の前に必ず割当て解除されます。

    • Vは、tryブロックに属するthrow eという形式のすべての文で、eの後に必ず割当て解除されます。

    • Vは、tryブロックで発生するassert文ごとに割当て解除されます。

    • Vは、tryブロックに属し、ブレーク・ターゲットにtry文が含まれている(または含まれている)すべてのbreak文の前に必ず割当て解除されます。

    • Vは、tryブロックに属し、その続行ターゲットにtry文が含まれるすべてのcontinue文の前に必ず割当て解除されます。

try文にfinallyブロックがない場合は、次のルールも適用されます。

  • Vtryブロックの後に[un]割り当てられ、Vtry文のcatchブロックごとに[un]割り当てられている場合、Vtry文の後に[un]割り当てられます。

try文にfinallyブロックがある場合、次のルールも適用されます。

  • Vは、次のうち少なくとも1つがtrueの場合、try文の後に必ず割り当てられます。

    • Vは、tryブロックの後に確実に割り当てられ、Vは、try文のすべてのcatchブロックの後に確実に割り当てられます。

    • Vは、finallyブロックの後に必ず割り当てられます。

  • Vfinallyブロックの後に確実に割当て解除されている場合、Vtry文の後に割当て解除されます。

  • Vtry文の前に確実に割り当てられている場合、Vfinallyブロックの前に必ず割り当てられます。

  • Vは、次のすべてに該当する場合、finallyブロックの前に必ず割当て解除されます。

    • Vは、tryブロックの後に必ず割当て解除されます。

    • Vは、tryブロックに属するすべてのreturn文の前に必ず割当て解除されます。

    • Vは、tryブロックに属するthrow eという形式のすべての文で、eの後に必ず割当て解除されます。

    • Vは、tryブロックで発生するassert文ごとに割当て解除されます。

    • Vは、tryブロックに属し、ブレーク・ターゲットにtry文が含まれている(または含まれている)すべてのbreak文の前に必ず割当て解除されます。

    • Vは、tryブロックに属し、その続行ターゲットにtry文が含まれるすべてのcontinue文の前に必ず割当て解除されます。

    • Vは、try文のcatchブロックごとに割当て解除されます。

16.3. 確定割当およびパラメータ

  • メソッドまたはコンストラクタの仮パラメータV(§8.4.1§8.8.1)は、メソッドまたはコンストラクタの本体の前に必ず割り当てられます(さらに、絶対に割当て解除されません)。

  • catch句の例外パラメータV(§14.20)は、catch句の本文の前に必ず割り当てられます(さらに、割当ては解除されません)。

16.4. 確定割当および配列初期化子

  • 空の配列イニシャライザの前に Vが[un]割り当てられている場合、Vは空の配列イニシャライザ(§10.6)のあとに[un]割り当てられます。

  • Vが配列イニシャライザの最後の変数イニシャライザのあとに割り当てられると、空でない配列イニシャライザのあとに Vが割り当てられます。

  • 配列イニシャライザの前に Vが[un]割り当てられている場合、Vは配列イニシャライザの最初の変数イニシャライザの前に割り当てられます。

  • Vが配列イニシャライザのeの左側にある変数イニシャライザの後に割り当てられている場合は、配列イニシャライザの他の変数イニシャライザeの前にVが割り当てられません。

16.5. 確定割当て定数と列挙定数

enum定数(§8.9.1)の前に変数が確実に割り当てられるか、または確実に割当て解除されるかを判断する規則は、§16.8に示されています。

これは、enum定数が基本的に、クラス・インスタンス作成式(§15.9)で初期化されるstatic finalフィールド(§8.3.1.1§8.3.1.2)であるためです。

  • Vがenum定数の前に確実に割り当てられている場合は、Vのスコープ内で宣言された引数を持たないenum定数のクラス本体の宣言の前に Vが割り当てられます。

  • Vがenum定数の最後の引数式のあとに確実に割り当てられている場合、Vのスコープ内で宣言された引数を持つenum定数のクラス本体の宣言の前に Vが必ず割り当てられます

enum定数のクラス本体内の任意のコンストラクトの明確な割当て/割当て解除ステータスは、クラスの通常のルールによって制御されます。

  • Vは、enum定数の前に割り当てられていない場合、enum定数の最初の引数の前に割り当てられます。

  • Vyの左側の引数のあとに割り当てられると、Vy (enum定数の引数ではなく、最初の引数)の前に割り当てられます。

16.6. 確定割当および匿名クラス

  • Vは、匿名クラスを宣言するクラスインスタンス作成式のあとに確実に Vが割り当てられている場合に、Vのスコープ内で宣言される匿名クラス宣言(§15.9.5)の前に必ず割り当てられます。

匿名クラスが列挙定数によって暗黙的に定義される場合は、§16.5のルールが適用されます。

16.7. 確定割当とメンバー・クラスおよびインタフェース

Cをクラスにし、VCの空白のfinalフィールドにします。 次に、

  • Vは、Cの任意のメンバークラスまたはインタフェース(§8.5§9.5)の宣言の前に必ず割り当てられます(さらに、絶対に未割り当てではありません)。

CVのスコープ内で宣言されたクラスとします。 次に、

  • VC宣言の前に確実に割り当てられている場合は、VCのメンバークラスまたはインタフェースの宣言の前に、Vが割り当てられます。

16.8. 確定割当および静的イニシャライザ

CVのスコープ内で宣言されたクラスとします。 次に、

  • VCの宣言の前に確実に割り当てられている場合、Vは必ず Cのenum定数(§8.9.1)または静的変数イニシャライザ(§8.3.2)の前に割り当てられます。

    静的変数イニシャライザまたは列挙定数の前に Vが確実に割り当て解除されていると結論付けることができる規則はありません。 Vは、Cの静的変数イニシャライザの前に絶対に割り当てられていないと非公式に結論付けることができますが、このような規則を明示的に指定する必要はありません。

Cをクラスにし、VCで宣言されたCの空白のstatic finalメンバー・フィールドにします。 次に、

  • Vは、左端のenum定数、静的イニシャライザ(§8.7)、または Cの静的変数イニシャライザの前に、必ず割り当て解除されます(さらに、確実に割り当てられません)。

  • Vは、前述のenum定数、静的イニシャライザ、または Cの静的変数イニシャライザの前に割り当てられます。ただし、左端のiff Vは、Cの静的変数イニシャライザ、静的イニシャライザ、または静的変数イニシャライザのあとに割り当てられます。

Cをクラスにし、VCのスーパークラスで宣言されたCの空白のstatic finalメンバー・フィールドにします。 次に、

  • Vは、Cのすべての列挙定数の前に確実に割り当てられます(さらに、絶対に割り当てられません)。

  • Vは、Cの静的イニシャライザの本体であるブロックの前に確実に割り当てられます(さらに、絶対に割り当てられません)。

  • Vは、Cのすべての静的変数イニシャライザの前に確実に割り当てられます(さらに、絶対に割り当てられません)。

16.9.  明確な割当て、コンストラクタおよびインスタンス・イニシャライザ

CVのスコープ内で宣言されたクラスとします。 次に、

  • VCの宣言の前に確実に割り当てられている場合、VCのコンストラクタ宣言(§8.8.7)またはインスタンス変数イニシャライザ(§8.3.2)の前に割り当てられます。

    コンストラクタ宣言またはインスタンス変数イニシャライザの前にVが確実に割当て解除されていると結論付けることができるルールはありません。 Cのコンストラクタ宣言またはインスタンス変数イニシャライザの前に、Vが確実に割当て解除されないことを非公式に結論付けることはできますが、そのようなルールを明示的に述べる必要はありません。

Cをクラスにし、VCで宣言されたCの空白のfinalstaticメンバー・フィールドにします。 次に、

  • Vは、C内のコンストラクタの宣言の前に確実に割当て解除されます(さらに言えば、確実に割り当てられていません)。

  • Vは、Cのコンストラクタのすべてのスーパークラス・コンストラクタ呼出し(§8.8.7.1)の後にVが確実に割当て解除されている場合、Vは、左端のインスタンス・イニシャライザ(§8.6)またはCのインスタンス変数イニシャライザ(V)の前に確実に割当て解除されます。

  • Vは、左端のインスタンス・イニシャライザ(§8.6)またはCのインスタンス変数イニシャライザ(Cが少なくとも1つのコンストラクタを宣言し、Cのすべてのコンストラクタが明示的なコンストラクタ呼出しを持ち、これらのコンストラクタのすべてのスーパークラス・コンストラクタ呼出しの後にVが必ず割り当てられます。

  • Vは、左端のiff V以外の Cのインスタンスイニシャライザまたはインスタンス変数イニシャライザの前に、Cの前のインスタンスイニシャライザまたはインスタンス変数イニシャライザのあとに[un]割り当てられます。

Cをクラスにし、VCのスーパークラスで宣言されたCの空白のfinalstaticメンバー・フィールドにします。 次に、

  • Vは、C内のコンストラクタの宣言の前に確実に割当て解除されます(さらに言えば、確実に割り当てられていません)。

  • Vは、Cのすべてのインスタンス・イニシャライザおよびインスタンス変数イニシャライザの前に確実に割り当てられます(さらに言えば、確実に割当て解除されていません)。

Cをクラスにし、VCの空白のfinal staticメンバー・フィールドにします。 次に、

  • Vは、Cのすべてのコンストラクタ宣言、インスタンス・イニシャライザおよびインスタンス変数イニシャライザの前に確実に割り当てられます(さらに言えば、確実に割当て解除されません)。

Cをクラスにし、Vを、Cのコンストラクタまたはインスタンス変数イニシャライザによって含まれる文Sによって宣言されたローカル変数にします。 次に、

  • コンストラクタ宣言またはインスタンス変数イニシャライザの前に、Vは必ず割当て解除されます(さらに、確実には割り当てられません)。

次のルールは、クラスCのコンストラクタ(§8.8.7)内に保持されます。

  • コンストラクタ宣言の前にVが[un]割り当てられている場合、Vはコンストラクタ本体(§8.8.7)のプロローグの前に割り当てられます。

  • Vがprologueの前に割り当てられていない場合、Vは空のprologueのあとに割り当てられます。

  • Vがプロローグの最後のステートメントのあとに割り当てられていない場合、Vは空でないプロローグのあとに割り当てられます。

  • Vがプロローグ後に割り当てられている場合、Vはコンストラクタ呼出し(§8.8.7.1)の前に割り当てられます。

  • 修飾子式の後に Vが[un]割り当てられている場合、Vは修飾スーパーコンストラクタ呼び出しの引数リストの前に割り当てられます。

  • Vが呼出しの前に[un]割り当てられている場合は、他のコンストラクタ呼出しの引数リストの前にVが割り当てられます。

  • Vが引数リストの右端の引数式の後に[un]割り当てられている場合、または引数リストが空で、Vが引数リストの前に[un]割り当てられている場合、Vはコンストラクタ呼出しの引数リストの後に[un]割り当てられます。

  • Cのスーパークラスで宣言されたCの空白のfinalstaticメンバー・フィールドは、スーパークラス・コンストラクタの起動後に確実に割り当てられます(さらに、割当ては解除されません)。

  • Vが呼出しの引数リストの後に[un]割り当てられている場合、他の変数Vはスーパークラス・コンストラクタ呼出しの後に[un]割り当てられます。

  • CまたはCのスーパークラスで宣言されたCの空白のfinalstaticメンバー・フィールドは、代替コンストラクタの起動後に確実に割り当てられます(さらに、割当ては解除されません)。

  • Vが呼出しの引数リストの後に[un]割り当てられている場合、他の変数Vは代替コンストラクタ呼出しの後に[un]割り当てられます。

  • 明示的なコンストラクタ呼出しがないコンストラクタ本体のエピローグの場合:

    • Cで宣言されたCの空白のfinalstaticメンバー・フィールドVは、VCの右端のインスタンス初期化またはインスタンス変数イニシャライザの後に[un]割り当てられている場合、またはCはインスタンス・イニシャライザまたはインスタンス変数イニシャライザを宣言せず、Vはコンストラクタ本体のプロローグの後に[un]割り当てられている場合、エピローグの前に割り当てられます。

    • Cのスーパークラスで宣言されたCの空白のfinalstaticメンバー・フィールドは、エピローグの前に確実に割り当てられます(さらに、割当ては解除されません)。

    • その他の変数 Vは、コンストラクタ本体のプロローグの後ろに Vが[un]割り当てられている場合に、エピローグの前に割り当てられます。

  • スーパークラス・コンストラクタ呼出しがあるコンストラクタ本体のエピローグの場合:

    • Cで宣言されたCの空白のfinalstaticメンバー・フィールドVは、VCの右端のインスタンス初期化またはインスタンス変数イニシャライザの後に[un]割り当てられている場合、またはCはインスタンス・イニシャライザまたはインスタンス変数イニシャライザを宣言せず、Vはスーパークラス・コンストラクタの起動後に[un]割り当てられる場合、エピローグの前に割り当てられます。

    • Vがスーパークラス・コンストラクタ呼出しの後に[un]割り当てられている場合、その他の変数Vはエピローグの前に[un]割り当てられます。

  • 代替コンストラクタ呼出しを含むコンストラクタ本体のエピローグの場合、Vが代替コンストラクタ呼出しの後に[un]割り当てられていると、Vはエピローグの前に[un]割り当てられます。

  • Vがエピローグの前に割り当てられていない場合は、空のエピローグのあとに Vが割り当てられます。

  • エピローグの最後のステートメントのあとに Vが[un]割り当てられている場合は、空でないエピローグのあとに Vが割り当てられます。

  • Vがそれぞれprologueまたはepilogueの前に割り当てられている場合は、Vはprologueまたはepilogueの最初の文の前に割り当てられません。

  • Vがプロローグまたはエピローグの Sの直前のステートメントの直後に割り当てられている場合、Vはプロローグまたはエピローグのほかのステートメント Sの前に割り当てられません。

  • スーパーコンストラクタの呼び出しの前に Vが[un]割り当てられている場合は、スーパーコンストラクタの呼び出しの修飾子式の前に Vが割り当てられます。

  • 引数リストの前に Vが[un]割り当てられている場合は、明示的なコンストラクタ呼び出しの左端の引数式の前に Vが割り当てられます。

  • Vxの左側の引数式の後に[un]割り当てられている場合、明示的なコンストラクタ呼出しの他の引数式xの前にVが割り当てられます。