Почему Java не имеет объявлений переменных с блочной областью?
Следующий метод не работает, потому что внутренний блок объявляет переменную с тем же именем, что и во внешнем блоке. По-видимому, переменные принадлежат к методу или классу, в котором они объявлены, а не к блоку, в котором они объявлены, поэтому я поэтому не могу написать небольшой небольшой временный блок для отладки, который происходит, чтобы вставить переменную во внешнюю область в тень на мгновение:
void methodName() {
int i = 7;
for (int j = 0; j < 10; j++) {
int i = j * 2;
}
}
Почти каждый язык с ограниченным блоком, который я когда-либо использовал, поддерживал это, в том числе тривиальные небольшие языки, на которых я писал интерпретаторы и компиляторы в школе. Perl может это сделать, как и схема, и даже C. Даже PL/SQL поддерживает это!
Какое обоснование для этого решения для Java?
Изменить: как заметил кто-то, у Java есть блок-область. Как зовут концепцию, о которой я спрашиваю? Хотелось бы, чтобы я больше помнил эти классы по языковому дизайну.:)
Ответы
Ответ 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;
}
}
}