Почему переменные, определенные в блоке case, доступны в других блоках case?

Возможный дубликат:
Почему переменные не локальны в операторах case?

Переменная, определенная в блоке области видимости, не может использоваться вне нее. Например, следующий фрагмент кода недействителен:

{
    int anothervar = 4;
}
{
    System.out.println(anothervar);
}

Но похоже, что блок case не создает отдельные области.

switch (mode) {
    case ONE:
        dosomething();
        return;
    case TWO:
        int[] someints = new int[] { 2, 3, 5, 7 };
        SomeObject obj = new SomeObject();
        return;
    case THREE:
        someints = new int[] { 1, 4, 6, 8, 9 };
        obj = new SomeObject();
        return;
}

Почему мне не нужно объявлять someints внутри блока case THREE?

Предположим mode = THREE, тогда объявление переменной someints никогда не будет достигнуто, потому что case TWO, где объявлено someints, пропускается. Или не так ли? Как это работает внутри?

(Выбранный ответ в Почему переменные не локальны в операторах case? утверждает, что оператор switch является внутренним набором команд jump, но все же это делает не объяснять, где объявлена ​​переменная someints.)

Ответ 1

локальная область переменных находится внутри блока, как указано в Документация по именам:

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

Определен блок, который имеет охватывающие фигурные скобки, как написано также в Блок-фактура и документация:

Блок представляет собой последовательность операторов, объявлений локального класса и локальные инструкции объявления переменных в фигурных скобках.

Ответ 2

Все внутри { } находится в одной области. Если вы выберете return; в случае TWO, например, вы можете использовать переменную в случае ТРИ, если она инициализирована.

Ответ 3

Вот почему вы иногда видите код с:

case 0: {
   // Stuff
}

Только {} разделяет блоки.

Ответ 4

Объем объявления помечен { ... }, и вы можете упасть с одного случая за секунду. Я признаю, что это дыра. Я верю в более старую версию Java, которой не разрешалось объявлять на уровне case и приходилось добавлять дополнительные фигурные скобки:

case 1: { int x; ... }

Ответ 5

В дополнение к другим ответчикам (как они заметили, область действия между {} является только одной здесь), я хотел бы заметить, что такая практика: объявление переменной в одном случае и использование ее в другой, загрязнен. Позже вы можете удалить или изменить какой-либо случай. И если он будет с декларацией, вам придется изменить другой случай. Это может привести к ошибкам.

Подумайте, почему ваша переменная должна быть в обоих случаях? Это ДЕЙСТВИТЕЛЬНО одно и то же или два разных?

Если это то же самое: Лучше объявите общие переменные в случае по умолчанию и поставьте его как первый.

switch (mode) {
    default:
        int[] someints;
        return;
    case ONE:
        dosomething();
        return;
    case TWO:
        someints = new int[] { 2, 3, 5, 7 };
        SomeObject obj = new SomeObject();
        return;
    case THREE:
        someints = new int[] { 1, 4, 6, 8, 9 };
        obj = new SomeObject();
        return;
}

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

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

Кстати: Это действительно хороший вопрос!