それで、私はいくつかの静的定数を持つこのクラスに取り組んでいます:
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";
}
}
ただし、コンパイルすると、3つのケースラベルのそれぞれでconstant expression required
エラーが発生します。
コンパイラーは、スイッチをコンパイルするために、コンパイル時に式を認識する必要があることを理解していますが、なぜFoo.BA_
定数ではないのですか?
コンパイラーは、スイッチをコンパイルするためにコンパイル時に式を知っている必要があることを理解していますが、なぜFoo.BA_が一定ではないのですか?
これらは、フィールドが初期化された後に実行されるコードの観点からは一定ですが、JLSが必要とする意味ではコンパイル時定数ではありません。 定数式の指定については §15.28定数式 を参照してください1。これは §4.12.4最終変数 を指し、次のように「定数変数」を定義します。
プリミティブ型またはString型の変数を呼び出します。これは最終変数であり、コンパイル時の定数式(§15.28)で初期化された定数変数です。変数が定数変数であるかどうかは、クラスの初期化(§12.4.1)、バイナリ互換性(§13.1、§13.4.9)、および明確な割り当て(§16)に影響を与える可能性があります。
あなたの例では、Foo.BA *変数には初期化子がないため、「定数変数」としての資格はありません。修正は簡単です。 Foo.BA *変数宣言を変更して、コンパイル時の定数式である初期化子を持たせます。
他の例(初期化子が既にコンパイル時の定数式である場合)では、変数をfinal
として宣言することが必要な場合があります。
enum
定数ではなくint
定数を使用するようにコードを変更することもできますが、それには別の制限がいくつかあります。
default
の既知の値ごとにcase
が存在する場合でも、mustenum
ケースを含めます。 enumのスイッチにデフォルトが必要な理由 を参照してくださいcase
ラベルは、enum
値に評価される式ではなく、すべて明示的なenum
値でなければなりません。1-定数式の制限は次のように要約できます。定数式a)プリミティブ型とString
のみを使用でき、b)リテラル(null
を除く)および定数変数のみを許可、c)おそらくサブ式として括弧で囲まれた定数式を許可、d)代入演算子、++
を除く演算子を許可--
またはinstanceof
、およびe)プリミティブ型への型キャストまたはString
のみを許可します。
これには、メソッドまたはラムダ呼び出しの形式new
、.class
は含まれないことに注意してください。 .length
または配列の添字。さらに、配列値、enum
値、プリミティブラッパータイプの値、ボックス化およびボックス化解除の使用は、a)のためにすべて除外されます。
定数式が必要を取得します。これは、定数から値を削除したためです。試してください:
public abstract class Foo {
...
public static final int BAR=0;
public static final int BAZ=1;
public static final int BAM=2;
...
}
Androidでこのエラーが発生しましたが、私の解決策は次のとおりです:
public static final int TAKE_PICTURE = 1;
の代わりに
public static int TAKE_PICTURE = 1;
それらはコンパイル時定数ではないからです。次の有効なコードを検討してください。
public static final int BAR = new Random().nextInt();
実行時にBAR
の値のみを知ることができます。
この例のような列挙型を使用できます。
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;
}
}
}
ソース: 列挙型のSwitchステートメント
これは何年も前に回答されたもので、おそらく関連性はありませんが、念のためです。この問題に直面したとき、if
の代わりにswitch
ステートメントを使用しただけで、エラーが解決しました。もちろんこれは回避策であり、おそらく「正しい」ソリューションではありませんが、私の場合はそれで十分でした。
スイッチ変数は、たとえば次のようなエラーを引き起こすこともあります。
switch(view.getTag()) {//which is an Object type
case 0://will give compiler error that says Constant expression required
//...
}
解決するには、変数をintにキャストする必要があります(この場合)。そう:
switch((int)view.getTag()) {//will be int
case 0: //No Error
//...
}
私の場合、私はこの例外を受け取っていました
switch (tipoWebServ) {
case VariablesKmDialog.OBTENER_KM:
resultObtenerKm(result);
break;
case var.MODIFICAR_KM:
resultModificarKm(result);
break;
}
2番目のケースでは、インスタンスvar.MODIFICAR_KM:
から定数を呼び出していましたが、クラスから直接VariablesKmDialog.OBTENER_KM
を使用する必要があります。
列挙型を使用することをお勧めします:)
これをチェックしてください:
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());
このようなことをしているときに、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:
}