1. ホーム
  2. java

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

2022-01-28 12:30:16

質問

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

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つのケースラベルのそれぞれで発生します。

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

どのように解決するのですか?

<ブロッククオート

コンパイラがスイッチをコンパイルするために、コンパイル時に式が分かっている必要があることは分かりましたが、なぜ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)のためすべて除外されます。