Pregunta

esto está permitido en java:

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

La palabra clave de mi pregunta es final . ¿Se permite hacer una variable final que cambie con cada ejecución del bucle? Me preguntaba esto porque final dice que no se puede cambiar el valor de la variable (solo se llama myFinalVariable = i ), pero estoy redefiniendo toda la variable con final int .

¿Son dos variables completamente diferentes con el mismo nombre, con la variable de la ejecución anterior del bucle ya en camino hacia el recolector de basura?

¿Fue útil?

Solución

Sí, está permitido. La palabra clave final significa que no puede cambiar el valor de la variable dentro de su alcance . Para su ejemplo de bucle, puede pensar en la variable que está fuera del alcance en la parte inferior del bucle, y luego volver al alcance con un nuevo valor en la parte superior del bucle. La asignación a la variable dentro del bucle no funcionará.

Otros consejos

Tienes razón, para cada iteración en el bucle, estás creando una nueva variable. Las variables comparten el mismo nombre, pero está bien porque no están en el mismo ámbito. El siguiente ejemplo no funcionará:

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

Una variable es solo una ubicación en la pila. Intente mantener sus variables con el menor alcance posible y trate de hacerlas definitivas. Sin embargo, el alcance y la final son solo cosas del código fuente ... desde el punto de vista de la generación de código / máquina virtual, realmente no importan en absoluto.

En su ejemplo específico, usar " int " no se crea basura Sin embargo, si se crearan objetos, en ambos casos la cantidad de basura y cuando la basura sería elegible para la limpieza sería idéntica.

Toma el siguiente código:

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;
        }
    }
}

El compilador produce un bytecode idéntico para cada método:

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

}

Al agregar otro método que declara que la variable fuera del bucle le da un bytecode ligeramente diferente debido al orden en que se declaran las variables). Tenga en cuenta que esta versión de la variable no se puede hacer final. Esta última versión no es la mejor manera (la variable final dentro del bucle es la mejor si puedes hacerlo):

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

}

Respondiendo, sí, puede marcar las variables en un bucle como 'final'. Aquí está el efecto de hacerlo (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.

}

La variable declarada dentro del bucle tiene el alcance solo hasta la ejecución única del bucle.

La declaración de la variable como final dentro del bucle no hace ninguna diferencia para la variable en el lado del bucle, pero si declaramos la variable fuera del bucle con el modificador final, el valor asignado al tipo primitivo u Objeto asignado a la variable de referencia no puede ser cambiado.

En el ejemplo siguiente, no hay problema con los dos primeros bucles, ambos bucles dan el mismo resultado, pero el tercer bucle da un error de tiempo de compilación.

prueba de clase pública {

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);
    }
}

}

Por favor, corrígeme si me equivoco.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top