foreach: почему переменная элемента не может быть объявлена ​​снаружи? - PullRequest
0 голосов
/ 13 мая 2019

"foreach" в Java, например,

for (Mouse mouse: mouses) {
    [...]
}

Мы не можем сделать:

Mouse mouse;
for (mouse: mouses) {
    [...]
}

Я цитирую geeksforgeeks : Since the i variable goes out of scope with each iteration of the loop, it is actually re-declaration each iteration

Таким образом, переменная будет объявлена ​​только один раз. Я не знаю, может ли это иметь очень небольшую оптимизацию, но это то, что я делаю в «нормальных» циклах на каждом языке.

Кроме того, таким образом последний элемент будет доступен и вне цикла. Это, например, значение по умолчанию в Python.


Как еще один связанный вопрос, есть какое-то преимущество, чтобы сделать

for (final Mouse mouse: mouses) {
    [...]
}

с точки зрения скорости, или mouse нельзя просто переназначить внутри цикла?

Ответы [ 2 ]

3 голосов
/ 13 мая 2019

В соответствии со спецификацией Java, цикл for-each (или расширенный for), который вы написали, расширился бы до:

for(java.util.Iterator i = mouses.iterator(); i.hasNext(); ) {
   Mouse mouse = (Mouse) i.next();
   [...]
}

( JLS )

Итакчтобы избежать «повторного выделения» вашей переменной mouse внутри цикла, вам нужно будет имитировать расширенную версию цикла for с объявлением для mouse снаружи:

Mouse mouse;
for(Iterator<Mouse> i = mouses.iterator(); i.hasNext(); ) {
   mouse = (Mouse) i.next();
   [...]
}

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

0 голосов
/ 13 мая 2019

По состоянию на другой связанный вопрос, final не влияет на производительность. Это всего лишь проверка (во время компиляции), что переменная не была переназначена во время ее действия. Компиляция

class Foo
{
    void foo(int[] arr)
    {
        for (/*final*/ int a : arr)
        {
            System.out.println(a);
        }
    }
}

производит точно такой же байт-код с или без выделенного final (по состоянию на javac 1.8.0_211)

...