所以,我正在处理这个类,它有几个静态常数:

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个case标签上都得到了一个常量表达式所需的错误。

我知道编译器需要表达式在编译时编译开关,但为什么不是Foo。BA_常数?


当前回答

在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:

            }

其他回答

在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:

            }

问题是整型和整数(我不知道为什么),改变整型字符串和它的工作

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

我建议使用以下方法:

public enum Animal {
    DOG("dog"), TIGER("tiger"), LION("lion");
    private final String name;

    Animal(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return this.name;
    }
}


public class DemoSwitchUsage {

     private String getAnimal(String name) {
         Animal animalName = Animal.valueOf(name);
         switch(animalName) {
         case DOG:
             // write the code required.
             break;
         case LION:
             // Write the code required.
             break;
         default:
             break;
         }
     }
}

我知道编译器需要表达式在编译时编译开关,但为什么不是Foo。BA_常数?

虽然从字段初始化后执行的任何代码的角度来看,它们都是常量,但它们不是JLS所要求的编译时常量;关于常量表达式1的规范,请参见§15.28常量表达式。这指的是§4.12.4最终变量,其中定义了一个“常量变量”如下:

我们把一个基本类型或String类型的变量称为常量变量,它是final的,并由编译时常量表达式初始化(§15.28)。变量是否是常量变量可能涉及类初始化(§12.4.1)、二进制兼容性(§13.1、§13.4.9)和定值(§16)。

在你的例子中,Foo。BA*变量没有初始化式,因此不符合“常量变量”的条件。解决办法很简单;改变Foo。BA*变量声明具有编译时常量表达式的初始化式。

在其他示例中(初始化式已经是编译时常量表达式),可能需要将变量声明为final。

你可以改变你的代码使用枚举而不是int常量,但这带来了另外两个不同的限制:

你必须包含一个默认的大小写,即使你有大小写为每个已知的enum值;参见为什么enum上的开关需要默认值? 大小写标签必须都是显式枚举值,而不是计算为枚举值的表达式。


1 -常量表达式的限制可以总结如下。常量表达式a)只能使用基本类型和String, b)只允许主变量是字面量(null除外)和常量变量,c)允许常量表达式可能是括号作为子表达式,d)允许操作符,除了赋值操作符,++,——或instanceof,以及e)只允许类型强制转换为基本类型或String。

注意,这并不包括任何形式的方法或lambda调用、new、.class. .length或数组下标。此外,数组值、枚举值、基本包装器类型的值、装箱和拆箱都被排除在外,因为a)。

在我的例子中,我得到这个异常是因为

switch (tipoWebServ) {
                            case VariablesKmDialog.OBTENER_KM:
                                resultObtenerKm(result);
                                break;
                            case var.MODIFICAR_KM:
                                resultModificarKm(result);
                                break;
                        }

在第二种情况下,我从实例var.MODIFICAR_KM调用常量:但我应该使用VariablesKmDialog。直接从类中获取OBTENER_KM。