создание конечных переменных внутри цикла

это разрешено в java:

for(int i=0;i<5;i++){
  final int myFinalVariable = i;
}

ключевое слово моего вопроса final. Можно ли сделать конечную переменную, которая изменяется с каждым запуском цикла? Мне было интересно это, потому что final говорит, что вы не можете изменить значение переменной (вызывая только myFinalVariable = i), но я переопределяю всю переменную с помощью final int.

являются ли они двумя совершенно разными переменными с одинаковым именем-с переменной из предыдущего запуска цикла уже направляешься к мусорщику?

5 ответов


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


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

final int myFinalVariable = 0;
for(int i=0;i<5;i++){
  myFinalVariable = i;
}

переменная-это просто местоположение в стеке. Постарайтесь сохранить переменные с как можно меньшей областью и попытаться сделать их окончательными. Однако scope и final - это просто исходный код... с точки зрения генерации кода / VM они вообще не имеют значения.

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

рассмотрим следующий код:

public class X
{
    public static void main(final String[] argv)
    {
        foo();
        bar();
    }

    private static void foo()
    {
        for(int i=0;i<5;i++)
        {
            final int myFinalVariable = i;
        }
    }

    private static void bar()
    {
        for(int i=0;i<5;i++)
        {
            int myFinalVariable = i;
        }
    }
}

компилятор создает идентичный байт-код для каждого метода:

public class X extends java.lang.Object{
public X();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method foo:()V
   3:   invokestatic    #3; //Method bar:()V
   6:   return

private static void foo();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iload_0
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_0
   8:   istore_1
   9:   iinc    0, 1
   12:  goto    2
   15:  return

private static void bar();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iload_0
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_0
   8:   istore_1
   9:   iinc    0, 1
   12:  goto    2
   15:  return

}

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

private static void car()
{
    int myFinalVariable;

    for(int i=0;i<5;i++)
    {
        myFinalVariable = i;
    }
}

private static void car();
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_1
   8:   istore_0
   9:   iinc    1, 1
   12:  goto    2
   15:  return

}

как ответил, Да, вы действительно можете пометить переменные в цикле как "final". Вот эффект от этого (Java 7, Eclipse Indigo, Mac OS X Lion).

for ( int i = 0; i < 5; i++ ) {

  // With 'final' you cannot assign a new value.
  final int myFinalVariable = i;  // Gets 0, 1, 2, 3, or 4 on each iteration.
  myFinalVariable = 7; // Compiler error: The final local variable myFinalVariable cannot be assigned.

  // Without 'final' you can assign a new value.
  int myNotFinalVariable = i;  // Gets 0, 1, 2, 3, or 4 on each iteration.
  myNotFinalVariable = 7; // Compiler is OK with re-assignment of variable's value.

}

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

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

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

открытый класс тест {

public static void main(String[] args) {
    for (int i = 0; i < 5; i++) {
        final int j= i;
        System.out.println(j);
    }
    for (int i = 0; i < 5; i++) {
        int j= i;
        System.out.println(j);
    }

    final int j;
    for (int i = 0; i < 5; i++) {
        j= i;
        System.out.println(j);
    }
}

}

пожалуйста, поправьте меня, если я ошибаюсь.