Java case表达式中的非静态变量?

Java case表达式中的非静态变量?,java,static,switch-statement,Java,Static,Switch Statement,我想从另一个类访问一个公共整数,以便在switch语句中使用,如下所示: StateManager sm = new StateManager(0); switch (localState) { case (sm.ALL_COMPANIES_REQUEST): { //do something } case (sm.GENERAL_TICKER_REQUEST): { //do this instead } 然而,这些变量

我想从另一个类访问一个公共整数,以便在switch语句中使用,如下所示:

StateManager sm = new StateManager(0);

switch (localState) {
    case (sm.ALL_COMPANIES_REQUEST): {
       //do something 
    }
    case (sm.GENERAL_TICKER_REQUEST): {
       //do this instead    
    }
然而,这些变量需要由多个线程访问,所以我不想让它们成为静态的。不幸的是,我得到一个错误,说大小写表达式必须是常量。没有任何方法可以改变这些变量,它们是常量,但如果不将它们标记为静态的,计算机似乎无法理解这一点。有人知道怎么避开这个吗

编辑:
嵌套这些类怎么样,这是一个选项,因为StateManager实际上只对具有上述switch语句的类有用。这是否足以单独使用final

如果它们是常量,那么声明它们为final static并在case语句中使用它们是没有问题的。多线程在这里没有影响。

如果它们是常量,那么将它们声明为最终静态并在case语句中使用它们是没有问题的。多线程在这里没有影响。

为什么不在枚举中声明这些字段

enum Request { 

    ALL_COMPANIES,
    GENERAL_TICKER

}

然后在交换机中使用它。

为什么不在枚举中声明这些字段

enum Request { 

    ALL_COMPANIES,
    GENERAL_TICKER

}

然后在开关中使用它。

尝试使用final,这将使其保持不变。

尝试使用final,这将使其保持不变。

要求switch语句上的值是常量表达式或枚举值;看

中描述了常量表达式。本质上,它是一个编译时常量表达式。这意味着这样的东西不会被编译:

    static final int foo = someString.length();
    ...
    switch (x) {
        case foo: ...  // case label is not a >>compile time<< constant
    }
但是,您对静态常量和线程的担心是没有根据的。最终字段的规范明确规定,无需同步即可安全读取这些字段;看

此外,即使字段不是最终字段,也不会出现死锁。如果线程没有在父对象或类上正确同步,则可能会看到字段的过时值

因此,你的问题的答案是:

如果常量是编译时常量,您可以将其声明为静态final,switch语句将编译,但是 如果该常量不是编译时常量,那么将其声明为static final将没有帮助。 嵌套类怎么样


这没有任何区别。

要求switch语句上的值是常量表达式或枚举值;看

中描述了常量表达式。本质上,它是一个编译时常量表达式。这意味着这样的东西不会被编译:

    static final int foo = someString.length();
    ...
    switch (x) {
        case foo: ...  // case label is not a >>compile time<< constant
    }
但是,您对静态常量和线程的担心是没有根据的。最终字段的规范明确规定,无需同步即可安全读取这些字段;看

此外,即使字段不是最终字段,也不会出现死锁。如果线程没有在父对象或类上正确同步,则可能会看到字段的过时值

因此,你的问题的答案是:

如果常量是编译时常量,您可以将其声明为静态final,switch语句将编译,但是 如果该常量不是编译时常量,那么将其声明为static final将没有帮助。 嵌套类怎么样


这不会有任何区别。

在按下开关之前,在线使用static/static+final修饰符

void m(){
final int a = 0;

switch(e)
case a : ...

}
woudl不起作用,因为void m将在编译完所有静态属性/方法后编译

void m()
{
switch(e)
case a : ...
}

final int a = 0;
不起作用,因为a的声明在开关之后

final int a = 0;

void m()
{
switch(e)
case a : ...
}
行得通

同样的原则

static A a = new A(b);
static B b = new B();
无法工作,因为JVM生成器正在逐行读取代码。。。它不像在C/C++中那样糟糕,但它仍然存在


开关在静态、最终常量、枚举上工作。。。它们不适用于hashSet条目,这是一件让我非常恼火的事情:在按下开关之前,在线使用static/static+final修饰符

void m(){
final int a = 0;

switch(e)
case a : ...

}
woudl不起作用,因为void m将在编译完所有静态属性/方法后编译

void m()
{
switch(e)
case a : ...
}

final int a = 0;
不起作用,因为a的声明在开关之后

final int a = 0;

void m()
{
switch(e)
case a : ...
}
行得通

同样的原则

static A a = new A(b);
static B b = new B();
无法工作,因为JVM生成器正在逐行读取代码。。。它不像在C/C++中那样糟糕,但它仍然存在


开关在静态、最终常量、枚举上工作。。。它们不适用于hashSet条目,这是一件让我非常生气的事情:D

哦,好吧,我想这可能会导致线程锁定。谢谢你的帮助!你认为使用来自多个线程的静态final会有问题的假设是不正确的。哦,好吧,我认为这可能会导致线程锁定。谢谢你的帮助!您认为使用来自多个线程的静态final会有问题的假设是不正确的。它们是final,不幸的是,这还不够。也许是因为它们是在另一个类中定义的?我不确定…他们是决赛,不幸的是那不是eno
啊。也许是因为它们是在另一个类中定义的?我不确定,开关不是条件,它们在堆中有特殊的子树,所以你必须考虑到,当你建立代码的时候,即使在某些属性声明之前或之后,开关看起来像是在你的代码上,或者它们在物理上没有看到对方,这就是为什么它不工作的原因。确定这些将是你的常量,或者尝试使用静态常数为每一个你想要切换的条目提供一个或多个实例。开关不是条件,它们在堆中有特殊的子树,所以你必须考虑这一点,并且想象当你建立代码时,甚至看起来在这个或那个线之前,开关是在你的代码上的。在物理上进行一些属性声明之后,它们彼此看不见,这就是为什么它不起作用。因此,如果确定这些将是常量,请尝试使用enum,或者尝试为每个要切换/大小写的条目使用带有静态常量的提供程序类。