提问者:小点点

将方法返回类型分配给case时常量表达式必填错误


我写了一个常量文件。

public interface IConstants {

    int SOME_CONSTANT = 6;
}

我写了一个包装方法来访问ConstantWrapper文件中的“SOME_CONSTANT”变量

public class ConstantWrapper {

   static ConstantWrapper mConstantWrapper = null;

    private ConstantWrapper(){

    }

    public static ConstantWrapper getInstance(){
        if(mConstantWrapper == null)
            mConstantWrapper = new ConstantWrapper();

        return mConstantWrapper;
    }

    public int getSomeConstantValue(){
        return IConstants.SOME_CONSTANT;
    }
}

现在,我想在switch case语句中访问包装方法,但我得到错误“需要常量表达式”。如何解决这个问题?

public class DemoClass{

private void checkSwitchCases(int value) {
        

        switch (value){
            case ConstantWrapper.getInstance().getSomeConstantValue(): // I get the error "constant expression required" in this line
                System.out.println("Case 6");
                break;

            case 8:
                System.out.println("Case 8");
                break;

            default:
                System.out.println("Case default");
                break;
        }
    }

}


共1个答案

匿名用户

你在这里应用了各种各样的反模式。看起来你遇到了一个问题(这里:我有一些我想管理的常量),并决定了一个问题的解决方案(一个接口,一个你错误地称为“包装器”的类),现在正在就你在实现解决方案时遇到的问题提出进一步的问题。但是,这不是一个好的解决方案,所以让我们回到最初的问题。

我写了一个常量文件

把一堆常量塞进一个接口过去很常见,但是现在我们有了枚举是星型导入,这不再是推荐的方法。只要把你的常量放在它们最相关的地方(不太可能是一个接口,但是如果你必须这样做,好吧)-并使用导入静态com.foo。ThatType。*;在一个想要使用它们的类中。不要在任何地方实现你的I常量-你的类的类型层次结构是公共信息,应该说明一些关于结构的事情,I常量毫无意义,这就是为什么这是坏风格。

I常量

不推荐这种匈牙利符号变体。如果您发现某个类型是相关的,您的IDE完全有能力通知您该类型是接口还是类。您不应该一开始就认为这是相关的代码:为什么IName是反模式的两个很好的理由。

类ConstantWrapper

这样做的目的是什么?为了维护ConstantWrapper类,你已经为自己做了大量的工作。我能猜测的唯一真正的好处是,你可以选择插入一个替代实现,但这意味着这些常量实际上首先不是常量,因此你得到的错误是正确的,解决方案是根本不使用开关,并且通常停止使用术语“常量”。将一个有一堆角的东西称为“圆形”是个坏主意。命名很难,但很重要。

公共静态ConstantWrapper getInstance()

你没有应用双重锁定,这意味着你可以有2个或更多的ConstantWrapper实例。如果你必须动态加载一个类,你应该依赖类加载器。然而,使用实际初始化的getInstance方法绝对没有任何意义:java不会在启动时加载所有类;它只是在第一次使用时加载一个类。鉴于ConstantWrapper的“首次使用”将是. getInstance(),java已经会在你想要的时候完全启动它们。因此:

  1. ConstantWrapper根本不应该存在。
  2. 如果你因为问题中没有说明的原因而必须拥有它,下面是如何做到的:
public class ConstantWrapper {
    private static final ConstantWrapper INSTANCE = new ConstantWrapper();
    public static ConstantWrapper getInstance() {
        return INSTANCE;
    }
}

这完全实现了您想要的(即,只有1个实例,并且该实例在需要之前不会初始化),但现在代码更少,并且没有错误。

常量表达式所需错误

方法调用不能是常量表达式周期。来源:Java语言规范。

如果初始化表达式是常量的,则在声明时初始化的静态和最终字段,其类型为原始或字符串,并且null不是常量表达式。这就是它结束的地方。所以,这工作:

class Example {
    public static final int FOO = 5;
}

class Foo {
    {
        switch (value) {
            case Example.FOO: // allowed; this is a constant expression
            case 10: // allowed; this is constant too
        }
    }
}

甚至像静态最终int A=5, B=10,C=A B;这样的东西也是允许的(C在这里也是常量,因为编译器可以在编译时弄清楚),但编译器不会走得太远。

没有办法让方法调用算作常量表达式,也没有办法告诉switch接受非常量表达式。