Чтобы понять суть этого вопроса ... [Обратите внимание, что реализации не-JVM могут работать по-другому, если это разрешено JLS ...]
Во-первых, имейте в виду, что локальная переменная "o" в примере является указателем, а не фактическим объектом.
Все локальные переменные размещены в стеке времени выполнения в 4-байтовых слотах. двойные и длинные требуют двух слотов; другие примитивы и указатели берут один. (Даже логические выражения занимают полный слот)
Для каждого вызова метода должен быть создан фиксированный размер стека времени выполнения. Этот размер определяется максимальными локальными переменными "slots", необходимыми в любой данной точке метода.
В приведенном выше примере обе версии кода требуют одинакового максимального количества локальных переменных для метода.
В обоих случаях будет сгенерирован один и тот же байт-код, который обновит один и тот же слот в стеке времени выполнения.
Другими словами, вообще никакого снижения производительности.
ОДНАКО, в зависимости от остальной части кода в методе, версия «объявление вне цикла» может фактически потребовать большего выделения стека времени выполнения. Например, сравнить
for (...) { Object o = ... }
for (...) { Object o = ... }
с
Object o;
for (...) { /* loop 1 */ }
for (...) { Object x =...; }
В первом примере оба цикла требуют одинакового выделения стека времени выполнения.
Во втором примере, поскольку "o" живет за пределами цикла, для "x" требуется дополнительный слот стека времени выполнения.
Надеюсь, это поможет,
- Скотт