2011-09-19 6 views
17

En final variable passed to anonymous class via constructor, Jon Skeet a mentionné que les variables sont passées à l'instance de classe anonyme via un constructeur généré automatiquement. Pourquoi devrais-je pas être en mesure de voir le constructeur en utilisant la réflexion dans ce cas:Passage de variables finales à des classes anonymes

public static void main(String... args) throws InterruptedException { 
final int x = 100; 
new Thread() { 
    public void run() { 
     System.out.println(x);  
     for (Constructor<?> cons : this.getClass() 
       .getDeclaredConstructors()) { 
      StringBuilder str = new StringBuilder(); 
      str.append("constructor : ").append(cons.getName()) 
        .append("("); 
      for (Class<?> param : cons.getParameterTypes()) { 
       str.append(param.getSimpleName()).append(", "); 
      } 
      if (str.charAt(str.length() - 1) == ' ') { 
       str.replace(str.length() - 2, str.length(), ")"); 
      } else 
       str.append(')'); 
      System.out.println(str); 
     } 
    } 

}.start(); 
Thread.sleep(2000); 

}

La sortie est:

100 
constructor : A$1() 

Répondre

16

Voici ce que votre programme imprime sur mon système:

100 
constructor : A$1() 

Ainsi, le constructeur est là . Cependant, il est sans paramètre. En regardant le désassemblage, ce qui se passe est que le compilateur se rend compte qu'il n'a pas besoin de passer x à run() puisque sa valeur est connue au moment de la compilation.

Si je change le code comme ceci:

public class A { 

    public static void test(final int x) throws InterruptedException { 
     new Thread() { 
      public void run() { 
       System.out.println(x); 
       for (Constructor<?> cons : this.getClass() 
         .getDeclaredConstructors()) { 
        StringBuilder str = new StringBuilder(); 
        str.append("constructor : ").append(cons.getName()) 
          .append("("); 
        for (Class<?> param : cons.getParameterTypes()) { 
         str.append(param.getSimpleName()).append(", "); 
        } 
        if (str.charAt(str.length() - 1) == ' ') { 
         str.replace(str.length() - 2, str.length(), ")"); 
        } else 
         str.append(')'); 
        System.out.println(str); 
       } 
      } 

     }.start(); 
     Thread.sleep(2000); 
     } 

    public static void main(String[] args) throws InterruptedException { 
     test(100); 
    } 

} 

Le constructeur qui obtient généré est maintenant:

constructor : A$1(int) 

Le seul argument est la valeur de x.

27

Dans ce cas, il est parce que 100 est une constante. Cela devient cuit dans votre classe.

Si vous changez x être:

final int x = args.length; 

... vous verrez Test$1(int) dans la sortie. (Ceci est, malgré qu'il ne soit explicitement déclarée Et oui, capturant plusieurs variables ajoute des paramètres au constructeur..)

+1

@Bohemian: Étant donné que je connais l'origine de la question, je pense que c'est :) –

Questions connexes