Domanda

è consentito in java:

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

La parola chiave della mia domanda è final . È consentito eseguire un'ultima variabile che cambia ad ogni esecuzione del ciclo? Mi chiedevo questo perché final dice che non puoi cambiare il valore della variabile (chiamando solo myFinalVariable = i ), ma sto ridefinendo l'intera variabile con final int .

Sono due variabili completamente diverse solo con lo stesso nome - con la variabile della precedente esecuzione del ciclo che sta già andando verso il garbage collector?

È stato utile?

Soluzione

Sì, è permesso. La parola chiave final significa che non puoi modificare il valore della variabile nel suo ambito . Per il tuo esempio di loop, puoi pensare alla variabile che esce dall'ambito nella parte inferiore del loop, per poi tornare all'ambito con un nuovo valore nella parte superiore del loop. L'assegnazione alla variabile all'interno del ciclo non funzionerà.

Altri suggerimenti

Hai ragione, per ogni iterazione nel ciclo, stai creando una nuova variabile. Le variabili condividono lo stesso nome, ma va bene perché non sono nello stesso ambito. Il prossimo esempio non funzionerebbe:

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

Una variabile è solo una posizione nello stack. Cerca di mantenere le variabili con un ambito il più piccolo possibile e cerca di renderle definitive. Tuttavia, scope e final sono solo cose del codice sorgente ... dal punto di vista della generazione del codice / VM non hanno alcuna importanza.

Nel tuo esempio specifico, usando " int " non viene creata immondizia. Tuttavia, se si trattasse di oggetti creati, per entrambi i casi la quantità di immondizia e quando l'immondizia sarebbe idonea per la pulizia sarebbe identica.

Prendi il seguente codice:

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

Il compilatore produce un bytecode identico per ciascun metodo:

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

}

L'aggiunta di un altro metodo che dichiara la variabile all'esterno del ciclo fornisce un bytecode leggermente diverso a causa dell'ordine in cui vengono dichiarate le variabili). Si noti che questa versione non può rendere definitiva la variabile. Quest'ultima versione non è il modo migliore (l'ultima variabile all'interno del loop è la migliore se puoi farlo):

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

}

Come risposto, Sì, puoi effettivamente contrassegnare le variabili in un ciclo come 'finale'. Ecco l'effetto di farlo (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.

}

Le variabili dichiarate all'interno del ciclo hanno l'ambito solo fino alla singola esecuzione del ciclo.

Dichiarare la variabile come finale all'interno del ciclo non fa alcuna differenza per la variabile nel lato del ciclo, ma se dichiariamo la variabile all'esterno del ciclo con modificatore finale, il valore assegnato al tipo primitivo o all'oggetto assegnato alla variabile di riferimento non può essere modificato.

Nell'esempio seguente non vi è alcun problema con i primi due loop, entrambi i loop forniscono lo stesso output, ma il terzo loop fornisce un errore di tempo di compilazione.

test di classe pubblica {

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

}

Per favore, correggimi se sbaglio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top