2009-03-04 10 views
39

est ce qui a permis en java:la création de variables finales dans une boucle

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 dernière variable qui change à chaque passage de la boucle? Je me demandais cela parce que final dit que vous ne pouvez pas changer la valeur de la variable (appelant seulement myFinalVariable = i), mais je redéfinis la variable entière avec final int.

S'agit-il de deux variables complètement différentes avec le même nom - avec la variable de l'exécution précédente de la boucle qui se dirige déjà vers le garbage collector?

Répondre

73

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 qui sort de la portée en bas de la boucle, puis revenir à la portée avec une nouvelle valeur en haut de la boucle. L'affectation à la variable dans la boucle ne fonctionnera pas.

11

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. exemple suivant ne pas travail:

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

Une variable est juste un emplacement sur la pile. Essayez de garder vos variables aussi petites que possible et essayez de les rendre définitives. Cependant, la portée et la finale ne sont que des choses de code source ... du point de vue de la génération de code/VM, elles n'ont pas vraiment d'importance.

Dans votre exemple spécifique, l'utilisation de "int" aucune poubelle est créée. Cependant, s'il s'agissait d'objets créés, dans les deux cas, la quantité de déchets et le moment où les déchets seraient éligibles pour le 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 bytecode 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 

} 

Ajouter une autre méthode qui déclare la variable en dehors de la boucle vous donner bytecode légèrement différente en raison de la ordonner que les variables soient déclarées). Notez que cette version la variable ne peut pas être rendue finale. Cette dernière version est pas la meilleure façon (la dernière variable dans la boucle est le meilleur si vous pouvez le faire):

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 

} 
2

Comme réponse, Oui, vous pouvez en effet marquer les variables dans une boucle comme « finale » . Voici l'effet de le faire (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. 

} 
2

Les variables déclarées à l'intérieur de la boucle n'ont d'étendue que jusqu'à la seule exécution de la boucle. Déclarer la variable comme finale dans la boucle ne fait aucune différence pour la variable dans la boucle, mais si nous déclarons la variable en dehors de la boucle avec le modificateur final alors la valeur assignée au type primitif ou à l'objet assigné à la variable de référence ne peut pas être changé.

Dans l'exemple ci-dessous, il n'y a pas de 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 public class {

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 ne me corriger si je me trompe.

Questions connexes