Question

est-ce autorisé en Java:

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

Le mot clé de ma question est final . Est-il permis de faire une variable finale qui change à chaque exécution de la boucle? Je me demandais cela parce que final dit que vous ne pouvez pas changer la valeur de la variable (appelant uniquement myFinalVariable = i ), mais je redéfinis la variable entière avec final int .

S'agit-il de deux variables complètement différentes portant simplement le même nom - la variable de la séquence précédente de la boucle se dirigeant déjà vers le garbage collector?

Était-ce utile?

La solution

Oui, c'est autorisé. Le mot clé final signifie que vous ne pouvez pas modifier la valeur de la variable dans son étendue . Pour votre exemple de boucle, vous pouvez penser à la variable sortant de la portée au bas de la boucle, puis revenant à la portée avec une nouvelle valeur en haut de la boucle. L’affectation de la variable dans la boucle ne fonctionnera pas.

Autres conseils

Vous avez raison, pour chaque itération de la boucle, vous créez une nouvelle variable. Les variables partagent le même nom, mais c'est correct car elles ne sont pas dans la même portée. L'exemple suivant ne fonctionnerait pas :

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

Une variable est simplement un emplacement sur la pile. Essayez de garder vos variables avec une portée aussi petite que possible et essayez de les rendre finales. Cependant, scope et final ne sont que des éléments de code source ... du point de vue de la génération de code / de la VM, ils n’ont aucune importance.

Dans votre exemple spécifique, utilisez " int " aucune poubelle n'est créée. Toutefois, s’il s’agissait de créer des objets, dans les deux cas, la quantité de déchets et le moment où ces déchets seraient admissibles au nettoyage seraient identiques.

Prenez le code suivant:

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

Le compilateur produit un code secondaire identique pour chaque méthode:

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'ajout d'une autre méthode déclarant la variable en dehors de la boucle donne un code différent légèrement différent en raison de l'ordre dans lequel les variables sont déclarées). Notez que cette version de la variable ne peut pas être rendue finale. Cette dernière version n’est pas la meilleure solution (la dernière variable de la boucle est la meilleure si vous le pouvez):

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

}

Comme répondu, vous pouvez effectivement marquer les variables d’une boucle comme "finales". Voici l’effet (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.

}

Les variables déclarées à l'intérieur de la boucle ont la portée uniquement jusqu'à l'exécution unique de la boucle.

La déclaration de la variable comme finale dans la boucle n'a aucune incidence sur la variable, mais si nous déclarons la variable en dehors de la boucle avec le modificateur final, la valeur affectée au type primitif ou à l'objet affecté à la variable de référence ne peut pas être changé.

Dans l'exemple ci-dessous, il n'y a aucun problème avec les deux premières boucles, les deux boucles donnent la même sortie, mais la troisième boucle donne une erreur de compilation.

test de classe publique {

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

}

S'il vous plaît, corrigez-moi si je me trompe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top