Объявление и инициализация переменных в 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
в том же блок какcase 1
и появляется после него, хотяcase 1
никогда не будет выполнена... таким образом, локальная переменная находится в области видимости и доступна для писать несмотря на то, что вы логически никогда не" выполняете " декларацию. (Объявление на самом деле не является" исполняемым", хотя инициализация есть.)если закомментировать
value = 2;
присваивание, компилятор все еще знает, на какую переменную вы ссылаетесь, но вы не пройдете через какой-либо путь выполнения, который присваивает ему значение, поэтому вы получаете ошибку как вы бы при попытке прочитать любую другую не-определенно-назначенную локальную переменную.я настоятельно рекомендую вам не чтобы использовать локальные переменные, объявленные в других случаях-это приводит к очень запутанному коду, как вы видели. Когда я ввожу локальные переменные в операторы switch (что я стараюсь делать редко-случаи должны быть очень короткими, в идеале), я обычно предпочитаю вводить новую область:
case 1: { int value = 1; ... break; } case 2: { int value = 2; ... break; }
Я считаю, что это яснее.
переменная была объявлена (как int), но не инициализирована (присвоено начальное значение). Подумайте о строку:
int value = 1;
как:
int value; value = 1;
The
int value
часть сообщает компилятору во время компиляции, что у вас есть переменная с именем value, которая является int. Элементvalue = 1
часть инициализирует его, но это происходит во время выполнения и не происходит вообще, если эта ветвь коммутатора не введена.
объявления обрабатываются во время компиляции и не зависят от поток выполнения кода. Так как
value
объявляется в местных объем блока переключателя, он годен к употреблению везде в том блоке от суть его декларации.
интеграция JEP 325: переключение выражений (предварительный просмотр) в сборках раннего доступа JDK-12. Есть определенные изменения, которые можно увидеть из Джон -
Область Действия Локальной Переменной - локальные переменные в случаях коммутатора теперь могут быть локальными для самого случая вместо всего блока коммутатора. Пример (похожий на то, что Джон пытался синтаксически также) учитывая
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); } }
Переключатель Выражений - если цель состоит в том, чтобы присвоить значение переменной, а затем использовать его, один раз можно использовать выражения 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' }