Объявление и инициализация переменных в Java переключатели

у меня есть сумасшедший вопрос о коммутаторах Java.

int key = 2;

switch (key) {
    case 1:
        int value = 1;
        break;
    case 2:
        value = 2;
        System.out.println(value);
        break;
    default:
        break;
}

Сценарий 1 - при key два он успешно печатать значение 2.
Сценарий 2 - Когда я собираюсь комментария value = 2 на case 2: она щебечет мол возможно, значение локальной переменной не было инициализировано.

вопросы :

Сценарий 1: Если поток выполнения не переходит в case 1: (при key = 2), тогда как он знает тип значение переменной как int?

Сценарий 2: если компилятор знает тип переменной value как int, тогда он должен иметь доступ к int value = 1; выражение case 1:.(Объявление и инициализация). Тогда почему это sqawrk, когда я собираюсь комментировать value = 2 на case 2:, говоря возможно, значение локальной переменной не было инициализировано.

4 ответов


операторы Switch нечетны с точки зрения области видимости, в основном. От раздел 6.3 JLS:

область объявления локальной переменной в блоке (§14.4) - это остальная часть блока, в котором появляется объявление, начиная с его собственного инициализатора и включая любые дополнительные деклараторы справа в оператор объявления локальной переменной.

в вашем случае, case 2 в том же блок as case 1 и появляется после него, хотя case 1 никогда не будет выполнена... таким образом, локальная переменная находится в области видимости и доступна для писать несмотря на то, что вы логически никогда не" выполняете " декларацию. (Объявление на самом деле не является "исполняемым", хотя инициализация есть.)

если закомментировать value = 2; назначение, компилятор все еще знает, какую переменную вы имеете в виду, но вы не пройдете через какой-либо путь выполнения, который присваивает ему значение, поэтому вы получаете ошибку как вы бы, когда пытаетесь прочитать любую другую не-определенно-назначенную локальную переменную.

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

case 1: {
    int value = 1;
    ...
    break;
}
case 2: {
    int value = 2;
    ...
    break;
}

Я считаю, что это яснее.


переменная была объявлена (как int), но не инициализирована (присвоено начальное значение). Подумайте о строку:

int value = 1;

As:

int value;
value = 1;

на int value часть сообщает компилятору во время компиляции, что у вас есть переменная value которая является int. The value = 1 часть инициализирует его, но это происходит во время выполнения и не происходит вообще, если эта ветвь коммутатора не введена.


от http://www.coderanch.com/t/447381/java-programmer-SCJP/certification/variable-initialization-within-case-block

объявления обрабатываются во время компиляции и не зависят от поток выполнения кода. С value объявляется в местных объем блока переключателя, он годен к употреблению везде в этом блоке от суть его декларации.


интеграция JEP 325: переключение выражений (предварительный просмотр) в сборках раннего доступа JDK-12. Есть определенные изменения, которые можно увидеть из Джон -

  1. Область Локальной Переменной - локальные переменные в случаях коммутатора теперь могут быть локальными для самого случая вместо всего блока переключателя. Пример (похожий на то, что Джон также попытался синтаксически) учитывая Day класс enum для дальнейшего объяснения :

    public enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }
    
    // some another method implementation
    Day day = Day.valueOf(scanner.next());
    switch (day) {
        case MONDAY,TUESDAY -> {
            var temp = "mon-tue";
            System.out.println(temp);
        }
        case WEDNESDAY,THURSDAY -> {
            var temp = Date.from(Instant.now()); // same variable name 'temp'
            System.out.println(temp);
        }
        default ->{
            var temp = 0.04; // different types as well (not mandatory ofcourse)
            System.out.println(temp);
        }
    }
    
  2. Переключатель Выражений - если цель состоит в том, чтобы присвоить значение переменной, а затем использовать ее, один раз можно использовать выражения switch. например,

    private static void useSwitchExpression() {
        int key = 2;
        int value = switch (key) {
            case 1 ->  1;
            case 2 -> 2;
            default -> {break 0;}
        };
        System.out.println("value = " + value); // prints 'value = 2'
    }