202

そのため、いくつかの静的定数を持つこのクラスに取り組んでいます。

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_定数ではないのはなぜですか?

4

14 に答える 14

174

コンパイラがスイッチをコンパイルするためにコンパイル時に式を認識する必要があることは理解していますが、Foo.BA_ 定数ではないのはなぜですか?

フィールドが初期化された後に実行されるコードの観点からは一定ですが、JLS が必要とする意味でのコンパイル時定数ではありません。定数式の指定については、§15.28 定数式参照してください。これは、次のように「定数変数」を定義する§4.12.4 最終変数を参照します。

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

あなたの例では、Foo.BA* 変数には初期化子がないため、「定数変数」としての資格はありません。修正は簡単です。コンパイル時の定数式である初期化子を持つように Foo.BA* 変数宣言を変更します。

他の例 (イニシャライザが既にコンパイル時の定数式である場合) では、final必要に応じて変数を宣言します。

enum定数ではなくを使用するようにコードを変更することもできますintが、それには別のいくつかの制限があります。

  • ;のすべての既知の値がある場合でも、ケースを含める必要があります。列挙型のスイッチにデフォルトが必要な理由を参照してください。defaultcaseenum
  • caseラベルはすべて、値に評価される式ではなく、明示的な値enumである必要がありenumます。

1 - 定数式の制限は次のように要約できます。定数式は、a) プリミティブ型Stringのみを使用できます。b) リテラル ( を除くnull) および定数変数のみであるプライマリを許可します。c) 部分式として括弧で囲まれた可能性がある定数式を許可します。d) 代入演算子++--またはinstanceofを除く演算子を許可します。 e) プリミティブ型またはプリミティブ型のみへの型キャストを許可しStringます。

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

于 2010-09-30T03:11:32.373 に答える
83

定数から値を除外したため、Constant expression requiredが表示されます。試す:

public abstract class Foo {
    ...
    public static final int BAR=0;
    public static final int BAZ=1;
    public static final int BAM=2;
    ...
}
于 2010-09-30T03:28:48.460 に答える
54

Androidでこのエラーが発生しましたが、私の解決策は次を使用することでした:

public static final int TAKE_PICTURE = 1;

それ以外の

public static int TAKE_PICTURE = 1;
于 2015-02-25T21:16:47.277 に答える
37

それらはコンパイル時定数ではないためです。次の有効なコードを検討してください。

public static final int BAR = new Random().nextInt();

BARの値は実行時にしかわかりません。

于 2010-09-30T03:13:48.767 に答える
18

次の例のように列挙型を使用できます。

public class MainClass {
enum Choice { Choice1, Choice2, Choice3 }
public static void main(String[] args) {
Choice ch = Choice.Choice1;

switch(ch) {
  case Choice1:
    System.out.println("Choice1 selected");
    break;
 case Choice2:
   System.out.println("Choice2 selected");
   break;
 case Choice3:
   System.out.println("Choice3 selected");
   break;
    }
  }
}

出典: enum を使用した Switch ステートメント

于 2011-07-21T14:27:18.860 に答える
0

次のようなことをしているときに、Android でこのエラーが発生しました。

 roleSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            switch (parent.getItemAtPosition(position)) {
                case ADMIN_CONSTANT: //Threw the error

            }

定数を宣言しているにもかかわらず:

public static final String ADMIN_CONSTANT= "Admin";

コードを次のように変更して問題を解決しました。

roleSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            String selectedItem = String.valueOf(parent.getItemAtPosition(position));
            switch (selectedItem) {
                case ADMIN_CONSTANT:

            }
于 2018-11-24T09:25:11.487 に答える
-1

列挙型を使用することをお勧めします:)

これをチェックしてください:

public enum Foo 
{
    BAR("bar"),
    BAZ("baz"),
    BAM("bam");

    private final String description;

    private Foo(String description)
    {
        this.description = description;
    }

    public String getDescription()
    {
        return description;
    }
}

次に、次のように使用できます。

System.out.println(Foo.BAR.getDescription());
于 2011-07-21T17:18:19.780 に答える