Область действия локальных переменных всегда должна быть наименьшей из возможных.
В вашем примере я предполагаю, str
что не используется вне while
цикла, иначе вы бы не задавали вопрос, потому что объявили его внутриwhile
цикла не было бы вариантом, так как он не компилируется.
Так, так как str
это не используется вне цикла, наименьший возможный простор для str
находится в пределах это время цикла.
Итак, ответ решительно, что str
абсолютно должно быть объявлено в цикле while. Нет, если, нет и нет, но нет.
Единственный случай, когда это правило может быть нарушено, - это если по какой-то причине жизненно важно, чтобы каждый тактовый цикл выжимался из кода, и в этом случае вы можете рассмотреть создание экземпляра чего-либо во внешней области видимости и его повторное использование вместо повторное создание его на каждой итерации внутренней области видимости. Однако это не относится к вашему примеру из-за неизменности строк в java: новый экземпляр str всегда будет создаваться в начале вашего цикла, и его нужно будет выбрасывать в конце, поэтому нет возможности оптимизировать там.
РЕДАКТИРОВАТЬ: (вставляя мой комментарий ниже в ответе)
В любом случае, правильный способ сделать что-то - это написать весь ваш код правильно, установить требования к производительности для вашего продукта, сравнить ваш конечный продукт с этим требованием, а если он его не удовлетворяет, тогда приступить к оптимизации. И в конечном итоге обычно происходит то, что вы находите способы обеспечить некоторые приятные и формальные алгоритмические оптимизации всего в нескольких местах, которые заставляют нашу программу соответствовать ее требованиям к производительности вместо того, чтобы обходить весь ваш код и настраивать и взламывать вещи в Для того чтобы сжать такты часов здесь и там.
Я сравнил байт-код этих двух (похожих) примеров:
Давайте посмотрим на 1. пример :
после того, как
javac Test.java
,javap -c Test
вы получите:Давайте посмотрим на 2. пример :
после того, как
javac Test.java
,javap -c Test
вы получите:Наблюдения показывают, что между этими двумя примерами нет никакой разницы . Это результат спецификаций JVM ...
Но во имя лучшей практики кодирования рекомендуется объявлять переменную в наименьшей возможной области (в этом примере она находится внутри цикла, так как это единственное место, где используется переменная).
источник
final
влюбленных: объявлениеstr
какfinal
вinside
пакете также не имеет значения =)Объявление объектов в наименьшем объеме улучшает читабельность .
Производительность не имеет значения для современных компиляторов. (В этом сценарии)
С точки зрения обслуживания, второй вариант лучше.
Объявите и инициализируйте переменные в одном и том же месте, в самой узкой области видимости.
Как сказал Дональд Эрвин Кнут :
то есть) ситуация, когда программист допускает, что соображения производительности влияют на дизайн фрагмента кода. Это может привести к конструкции, которая не так чист , как это могло бы быть или код , который является неправильным, так как код осложняется по оптимизации и программист отвлекается оптимизации .
источник
если вы хотите использовать и
str
внешнюю петлю; объявить это снаружи. в противном случае вторая версия в порядке.источник
Пожалуйста, перейдите к обновленному ответу ...
Для тех, кто заботится о производительности, удалите System.out и ограничьте цикл до 1 байта. При использовании double (тест 1/2) и использовании String (3/4) истекшее время в миллисекундах приводится ниже для 64-битной Windows 7 Professional и JDK-1.7.0_21. Байт-коды (также приведены ниже для test1 и test2) не совпадают. Мне было лень проверять изменчивые и относительно сложные объекты.
двойной
Тест1 взял: 2710 мсек
Тест2 взял: 2790 мсек
Строка (просто замените double на строку в тестах)
Тест3 взял: 1200 мсек
Test4 взял: 3000 мсек
Компиляция и получение байт-кода
ОБНОВЛЕННЫЙ ОТВЕТ
Это действительно нелегко сравнить производительность со всеми оптимизациями JVM. Тем не менее, это несколько возможно. Лучший тест и подробные результаты в Google Caliper
Частичный тестовый код для двойной декларации
Это не идентично коду выше. Если вы просто кодируете фиктивный цикл, JVM пропускает его, так что по крайней мере вам нужно что-то присвоить и вернуть. Это также рекомендуется в документации суппорта.
источник
Одним из решений этой проблемы может быть предоставление переменной области, инкапсулирующей цикл while:
Они будут автоматически разыменовываться по окончании внешней области видимости.
источник
Внутри, чем меньше область видимости переменной, тем лучше.
источник
Если вам не нужно использовать
str
цикл while (связанный с областью действия), тогда второе условие, т.е.лучше, если вы определяете объект в стеке, только если значение
condition
true. Т.е. используйте его, если вам это нужноисточник
Я думаю, что лучшим ресурсом для ответа на ваш вопрос будет следующий пост:
Разница между объявлением переменных до или в цикле?
Насколько я понимаю, эта вещь будет зависеть от языка. IIRC Java оптимизирует это, так что нет никакой разницы, но JavaScript (например) будет распределять всю память каждый раз в цикле. В частности, в Java, я думаю, вторая будет работать быстрее, когда будет выполнено профилирование.
источник
Как многие люди указали,
это НЕ лучше , чем это:
Так что не объявляйте переменные вне их областей, если вы не используете их повторно ...
источник
Объявление String str вне цикла wile позволяет ссылаться на него внутри и снаружи цикла while. Объявление String str внутри цикла while позволяет ссылаться на него только внутри цикла while.
источник
Переменные должны быть объявлены как можно ближе к месту их использования.
Это облегчает RAII (получение ресурсов является инициализацией) .
Он сохраняет область действия переменной. Это позволяет оптимизатору работать лучше.
источник
Согласно руководству по разработке Google Android, область действия переменной должна быть ограничена. Пожалуйста, проверьте эту ссылку:
Предел переменной области
источник
str
Переменная будет доступна и зарезервировали место в памяти даже после того, как в то время как выполняется ниже кода.str
Переменная не будет доступна , а также память будет выпущен , который был выделенstr
переменной в коде ниже.Если мы последуем за вторым, это наверняка уменьшит нашу системную память и увеличит производительность.
источник
Объявление внутри цикла ограничивает область действия соответствующей переменной. Все зависит от требований проекта к области действия переменной.
источник
Действительно, вопрос, изложенный выше, является проблемой программирования. Как бы вы хотели запрограммировать свой код? Где вам нужен STR для доступа? Нет смысла объявлять переменную, которая используется локально как глобальная переменная. Основы программирования я считаю.
источник
Эти два примера приводят к одному и тому же. Однако первый предоставляет вам возможность использовать
str
переменную вне цикла while; второй нет.источник
Предупреждение для почти всех в этом вопросе: вот пример кода, где внутри цикла он может быть в 200 раз медленнее на моем компьютере с Java 7 (и потребление памяти также немного отличается). Но речь идет о распределении, а не только сфере.
Вывод: в зависимости от размера локальной переменной, разница может быть огромной, даже с небольшими переменными.
Просто сказать, что иногда снаружи или внутри цикла имеет значение.
источник
bigStuff[(int) (value % STUFF_SIZE)] = value;
(Попробуйте значение 2147483649L)Я думаю, что размер объекта также имеет значение. В одном из моих проектов мы объявили и инициализировали большой двумерный массив, который заставлял приложение генерировать исключение нехватки памяти. Вместо этого мы переместили объявление из цикла и очистили массив в начале каждой итерации.
источник
У вас есть риск того,
NullPointerException
что вашcalculateStr()
метод вернет null, а затем вы попытаетесь вызвать метод на str.В более общем смысле, избегайте использования переменных с нулевым значением. Это сильнее для атрибутов класса, кстати.
источник
NullPointerException.
при попытке этого кодаreturn str;
возникнет ошибка компиляции.