В Java, переменные должны быть объявлены в верхней части функции, или как они необходимы? - PullRequest
35 голосов
/ 11 сентября 2009

Я очищаю Java-код для того, кто запускает свои функции, объявляя все переменные сверху и инициализируя их как null / 0 / что угодно, вместо того, чтобы объявлять их по мере необходимости позже.

Каковы конкретные рекомендации для этого? Есть ли причины для оптимизации того или иного способа, или это просто хорошая практика? Есть ли случаи, когда допустимо отклоняться от того, как правильно это сделать?

Ответы [ 12 ]

79 голосов
/ 11 сентября 2009

Объявите переменные как можно ближе к первому месту, в котором вы их используете. На самом деле это не имеет ничего общего с эффективностью, но делает ваш код более читабельным. Чем ближе объявляется переменная к месту ее использования, тем меньше прокрутки / поиска вы должны выполнять при чтении кода позже. Объявление переменных ближе к первому месту, которое они используют, также естественно сужает их scope .

33 голосов
/ 11 сентября 2009

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

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

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

20 голосов
/ 11 сентября 2009

Из Java Code Conventions , Глава 6 по объявлениям :

6,3 Размещение

Размещать объявления только в начале блоков. (Блок - это любой код в окружении фигурных скобок "{" и "}".) Не ждите, чтобы объявить переменные до их первого использования; это может запутать неосторожный программист и затрудняют код портативность в рамках.

void myMethod() {
    int int1 = 0;         // beginning of method block

    if (condition) {
        int int2 = 0;     // beginning of "if" block
        ...
    }
}

Единственное исключение из правил индексы для циклов, которые в Java может быть объявлено в операторе for:

for (int i = 0; i < maxLoops; i++) { ... }

Избегайте местных объявлений, которые скрывают объявления на более высоких уровнях. За Например, не объявляйте то же самое имя переменной во внутреннем блоке:

int count;
...
myMethod() {
    if (condition) {
        int count = 0;     // AVOID!
        ...
    }
    ...
}
14 голосов
/ 11 сентября 2009

Если у вас есть несколько переменных, используемых в различных изолированных местах внутри тела функции, ваша функция слишком велика.

Если ваша функция имеет удобный для понимания размер, нет никакой разницы между «все сразу» и «так, как нужно».

Единственная непередаваемая переменная будет в теле оператора for.

for( Iterator i= someObject.iterator(); i.hasNext(); ) 
5 голосов
/ 11 сентября 2009

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

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

5 голосов
/ 11 сентября 2009

Я делаю то же самое в данный момент. Все переменные в коде, который я переделываю, объявляются в верхней части функции. Я видел, как просматривал это, что несколько переменных объявляются, но НИКОГДА не используются, или они объявляются, и с ними выполняются операции (т.е. анализ String и затем установка объекта Calendar с датой / значения времени из строки), но затем полученный Calendar объект НИКОГДА не используется.

Я проверяю и очищаю их, беря объявления сверху и перемещая их вниз в функции к месту ближе к месту его использования.

5 голосов
/ 11 сентября 2009

Я обнаружил, что объявление их по мере необходимости приводит к меньшему количеству ошибок, чем объявление их в начале. Я также обнаружил, что объявление их в минимально возможном объеме также предотвращает ошибки.

Когда я посмотрел байт-код, сгенерированный расположением объявления несколько лет назад, я обнаружил, что они более или менее идентичны. Были случайные различия в зависимости от того, когда они были назначены. Даже что-то вроде:

for(Object o : list) {
   Object temp = ...;  //was not "redeclared" every loop iteration
}

против

Object temp;
for(Object o : list) {
   temp = ...; //nearly identical bytecoode, if not exactly identical.
}

Получилось более или менее идентично

4 голосов
/ 09 февраля 2018

Принцип: размещайте объявления локальных переменных как можно ближе к их первому использованию, а НЕ просто вверху метода. Рассмотрим этот пример:

/** Return true iff s is a blah or a blub. */
public boolean checkB(String s) {
    // Return true if s is a blah
    ... code to return true if s is a blah ... 

    // Return true if s is a blub. */
    int helpblub= s.length() + 1;
    ... rest of code to return true is s is a blah.

    return false;
}

Здесь локальная переменная helpblub помещается, где это необходимо, в код, чтобы проверить, является ли s клубом. Это часть кода, которая реализует «Вернуть истину, если это пустяк». Не имеет абсолютно никакого логического смысла помещать объявление helpblub в качестве первого утверждения метода. Бедный читатель будет удивляться, почему эта переменная существует? Для чего это?

4 голосов
/ 01 января 2017

С Руководство по стилю Google Java :

4.8.2.2 Заявлено при необходимости

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

Хорошо, я бы следовал тому, что делает Google, на поверхностном уровне могло бы показаться, что объявление всех переменных в начале метода / функции было бы "аккуратнее", совершенно очевидно, что было бы полезно объявить переменные как необходимо. Это субъективно, что бы ни казалось вам интуитивным.

4 голосов
/ 11 сентября 2009

Я думаю, что на самом деле объективно доказуемо, что стиль объявления наверху более подвержен ошибкам.

Если вы мутируете тестовый код в любом стиле, перемещая строки случайным образом (чтобы имитировать слияние или неудачное срезание или вставка), тогда стиль объявления на вершине имеет больше шансов на функционально неправильно.

Я не думаю, что объявить на вершине имеет какое-либо соответствующее преимущество, которое не сводится к личным предпочтениям.

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

...