1. ホーム
  2. java

[解決済み】Javaのswitch文。定数式が必要だが、定数である

2022-05-10 13:55:08

質問

私はいくつかの静的定数を持つこのクラスで作業しています。

public abstract class Foo {
    ...
    public static final int BAR;
    public static final int BAZ;
    public static final int BAM;
    ...
}

それから、定数を元に関連する文字列を取得する方法が欲しいです。

public static String lookup(int constant) {
    switch (constant) {
        case Foo.BAR: return "bar";
        case Foo.BAZ: return "baz";
        case Foo.BAM: return "bam";
        default: return "unknown";
    }
}

ところが、コンパイルすると constant expression required というエラーが3つのケースラベルのそれぞれで発生します。

コンパイラがswitchをコンパイルするためにコンパイル時に式が分かっている必要があることは理解できますが、なぜ Foo.BA_ は定数なのでしょうか?

どのように解決する?

<ブロッククオート

コンパイラがswitchをコンパイルするために、コンパイル時に式が分かっている必要があることは分かりましたが、なぜFoo.BA_は一定ではないのでしょうか?

フィールドが初期化された後に実行されるあらゆるコードの観点からは定数ですが、それらは コンパイル時定数 であり、JLS が要求する意味でのコンパイル時定数ではありません。 §15.28節 定数式 の指定については 定数式 1 . これは §4.12.4節 最終変数 では、次のように"定数変数"を定義しています。

プリミティブ型またはString型で、コンパイル時の定数式(15.28節)で初期化されたfinalの変数を定数変数と呼びます。変数が定数変数であるかどうかは、クラスの初期化 (§12.4.1) 、バイナリ互換性 (§13.1, §13.4.9) 、定型代入 (§16) に関して意味を持つことがあります。

あなたの例では、Foo.BA* 変数は初期化子を持たないので、"定数変数" として適格ではありません。 修正方法は簡単で、Foo.BA* 変数の宣言を変更して、コンパイル時の定数式である初期化子を持たせることです。

他の例では (初期化子がすでにコンパイル時の定数式である場合)、変数の宣言を final と宣言することが必要かもしれません。

を使用するようにコードを変更することができます。 enum ではなく int 定数ではなく、定数とすることをお勧めします。

  • あなたは を含める必要があります。 default がある場合でも case の既知の値すべてに対して enum を参照してください。 なぜ enum のスイッチに default が必要なのですか?
  • case ラベルは全て明示的でなければなりません。 enum に評価される式ではなく、値でなければなりません。 enum 値に評価される式ではありません。

1 - 定数式の制限をまとめると、以下のようになります。 定数式 a) プリミティブ型と String のみを使用することができます。 b) リテラルのプライマリ( null ) と定数変数のみを許可する。 c) サブ式として括弧で囲まれた定数式を許可する。 d) 代入演算子以外の演算子を許可する。 ++ , -- または instanceof e) プリミティブ型への型キャストを許可する、または String だけである。

メソッドやラムダ呼び出しの形式は含まれないことに注意してください。 new , .class . .length または配列の添え字を使用します。 さらに、配列の値のあらゆる使用。 enum 値,プリミティブラッパ型の値,ボックス化及びアンボックス化の使用は,a)のため,すべて除外される。