Подтвердить что ты не робот

Почему Java не имеет объявлений переменных с блочной областью?

Следующий метод не работает, потому что внутренний блок объявляет переменную с тем же именем, что и во внешнем блоке. По-видимому, переменные принадлежат к методу или классу, в котором они объявлены, а не к блоку, в котором они объявлены, поэтому я поэтому не могу написать небольшой небольшой временный блок для отладки, который происходит, чтобы вставить переменную во внешнюю область в тень на мгновение:

void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
}

Почти каждый язык с ограниченным блоком, который я когда-либо использовал, поддерживал это, в том числе тривиальные небольшие языки, на которых я писал интерпретаторы и компиляторы в школе. Perl может это сделать, как и схема, и даже C. Даже PL/SQL поддерживает это!

Какое обоснование для этого решения для Java?

Изменить: как заметил кто-то, у Java есть блок-область. Как зовут концепцию, о которой я спрашиваю? Хотелось бы, чтобы я больше помнил эти классы по языковому дизайну.:)

4b9b3361

Ответ 1

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

в примере, как тривиальный, как ваш, его очевидный, но в большом блоке кода, случайное переопределение переменной может быть не очевидным.

ETA: он также может быть связан с обработкой исключений в java. Я думал, что часть этого вопроса обсуждалась в вопросе, связанном с тем, почему переменные, объявленные в разделе try, недоступны в области catch/finally.

Ответ 2

Ну, строго говоря, у Java есть объявления переменных с расширенной областью; так что это ошибка:

void methodName() {
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
  System.out.println(i); // error
}

Потому что "i" не существует вне блока for.

Проблема заключается в том, что Java не позволяет создавать переменную с тем же именем другой переменной, которая была объявлена ​​во внешнем блоке того же метода. Как говорили другие люди, предположительно это было сделано для предотвращения ошибок, которые трудно идентифицировать.

Ответ 3

Потому что это не редкость для писателей делать это намеренно, а затем полностью испортить его, забыв, что теперь есть две переменные с тем же именем. Они меняют имя внутренней переменной, но оставляют код, который использует переменную, которая теперь неинтересно использует ранее затененную переменную. Это приводит к тому, что программа все еще компилируется, но выполняется с ошибкой.

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

Там так мало пользы, чтобы позволить этому затенению, что они исключили его как слишком опасное. Серьезно, просто вызовите новую переменную что-то еще, и проблема исчезнет.

Ответ 4

Это приводит к ошибкам, которые трудно обнаружить, я думаю. Это похоже на С#.

Паскаль не поддерживает это, так как вы должны объявлять переменные над телом функции.

Ответ 5

Основополагающее предположение в этом вопросе неверно.

Java имеет область видимости блока. Но он также имеет иерархию области видимости, поэтому вы можете ссылаться на i в цикле for, но не j вне цикла for.

public void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    i = j * 2;
  }

  //this would cause a compilation error!
  j++;
}

Я не могу на всю жизнь понять, почему вы хотите, чтобы предметные области вел себя по-другому. Невозможно определить, к какому i вы относились к внутри цикла for, и я бы поставил шансы на 99,999% времени, когда вы хотите ссылаться на i внутри метода.

Ответ 6

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

void methodName() {
    int i = 7;
    for (int j = 0; j < 10; j++) {
        int i = outer.i * 2;
        if(i > 10) {
            int i = outer.outer.i * 2 + outer.i;
        }
    }
}