2010-02-12 6 views
3

En Java, je sais qu'il est possible de faire quelque chose comme ceci:Se référant à des champs non définitifs d'une classe englobante dans une classe interne anonyme en Java

public class Greeter { 
    public void greetEventually() { 
     final String greeting = "Hello!"; 
     Job j = new Job() { 
      public void run() { 
       System.out.println(greeting); 
      } 
     }; 
     j.schedule(); 
    } 
} 

Ce serait exécuter le Job anonyme à un point dans le futur. Cela fonctionne car les classes anonymes sont autorisées à se référer aux variables finales dans la portée englobante.

Ce que je ne suis pas sûr est le cas suivant:

public class Greeter { 
    private String greeting; 

    // ... Other methods that might mutate greeting ... 

    public void greetEventually() { 
     Job j = new Job() { 
      public void run() { 
       System.out.println(greeting); 
      } 
     }; 
     j.schedule(); 
    } 
} 

Dans ce cas, mon anonyme Job fait référence à un champ non-finale de la classe englobante. Lorsque le travail s'exécutera, verrai-je la valeur du champ greeting tel qu'il était lors de la création du Job, ou tel qu'il est en cours d'exécution? Je pense que je connais la réponse, mais je pensais que c'était une question intéressante, et au début, il nous a fallu que quelques collègues et moi-même réfléchissions quelques minutes de plus.

Répondre

9

La valeur greeting s'affiche au moment de l'exécution de l'anonyme Job.

Le modificateur final est requis uniquement pour les variables locales et non pour les variables membres.

+0

Voici comment je pensais que cela fonctionnait. A propos, la seule raison pour laquelle j'ai mentionné explicitement les champs ** non-finaux est que si le champ est définitif, le comportement est clair. –

+0

Yup. Nous avons pensé que ce serait une bonne question à avoir dans le dossier. Mike tu devrais accepter celui-ci. –

-1

Le dernier modificateur est appliqué aux variables locales uniquement pour fournir des variables pour chaque instance de la classe interne. Nous utilisons donc: final String saleting;

Lorsque vous n'avez besoin que d'une instance de la variable (comme dans le cas de constantes ou de ressources communes), utilisez: private String salutation;

1

Vous accédez au champ via (l'extérieur) this). Vous pouvez considérer this comme une variable locale final. Seul le local est final, l'objet pointé n'est pas (nécessairement) constant. Imaginez une variable locale avec la même valeur que this et il devrait être clair.

public class Greeter { 
    private String greeting; 

    // ... Other methods that might mutate greeting ... 

    public void greetEventually() { 

     private final Greeter greeter = this; // <--- 

     Job j = new Job() { 
      public void run() { 
       System.out.println( greeter.greeting ); // <--- 
      } 
     }; 
     j.schedule(); 
    } 
} 
Questions connexes