Нестатическая переменная в случае выражения? - PullRequest
1 голос
/ 12 марта 2011

Я хотел бы получить доступ к общедоступному целому числу из другого класса для использования в операторе switch, как показано ниже:

StateManager sm = new StateManager(0);

switch (localState) {
    case (sm.ALL_COMPANIES_REQUEST): {
       //do something 
    }
    case (sm.GENERAL_TICKER_REQUEST): {
       //do this instead    
    }

Однако эти переменные должны быть доступны для нескольких потоков, поэтому я не хочу делать их статичными. К сожалению, я получаю сообщение о том, что выражения в регистре должны быть постоянными. Нет методов, которые изменяют эти переменные, они являются постоянными, но кажется, что без маркировки их static компьютер не может понять это. Кто-нибудь знает, как обойти это?

Edit: Как насчет вложения классов, это вариант, так как StateManager действительно полезен только для класса с оператором switch выше. Будет ли этого достаточно, чтобы использовать final?

Ответы [ 5 ]

5 голосов
/ 12 марта 2011

Требуется, чтобы значения в выражении switch были константными выражениями или значениями enum;см. JLS 14.11 .

Постоянное выражение описано в JLS 15,28 .По сути, это константное время компиляции .Таким образом, это означает, что что-то подобное не скомпилируется:

    static final int foo = someString.length();
    ...
    switch (x) {
        case foo: ...  // case label is not a >>compile time<< constant
    }

Однако ваша забота о статических константах и ​​потоках необоснованна.Спецификация полей final, в частности, гласит, что их можно безопасно читать без синхронизации;см JLS 17,5 .

(Кроме того, вы не получите взаимоблокировки, даже если поля не являются окончательными. То, что вы получите, это потоки возможно просмотр устаревших значений поля, если они не синхронизируютсядля родительского объекта или класса.)

Итак, ответ на ваш вопрос:

  • если константа является константой времени компиляции, вы можете просто объявить как static finalи оператор switch будет компилироваться, но
  • , если константа НЕ является константой времени компиляции, то объявление ее как static final не поможет.

Как насчет вложенных классов?

Это не будет иметь никакого значения.

2 голосов
/ 12 марта 2011

Если они являются константами, нет проблем с их объявлением final static и использованием их в выражении case. Многопоточность здесь не влияет.

1 голос
/ 12 марта 2011

попробуйте использовать final, чтобы сделать его постоянным.

1 голос
/ 12 марта 2011

Почему бы не объявить эти поля внутри перечисления?

enum Request { 

    ALL_COMPANIES,
    GENERAL_TICKER

}

, а затем используйте это в вашем коммутаторе.

0 голосов
/ 20 апреля 2013

Использование статического / статического + финального модификатора в строке перед тем, как будет представлен переключатель.

void m(){
final int a = 0;

switch(e)
case a : ...

}

не будет работать, потому что 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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...