2011-09-19 13 views
17

In final variable passed to anonymous class via constructor, Jon Skeet ha affermato che le variabili vengono passate all'istanza della classe anonima tramite un costruttore generato automaticamente. Perché dovrei non essere in grado di vedere il costruttore utilizzando la riflessione in questo caso:Passaggio di variabili finali a classi anonime

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

}

L'output è:

100 
constructor : A$1() 

risposta

16

Ecco ciò che il programma stampa sul mio sistema:

100 
constructor : A$1() 

Così il costruttore è lì . Tuttavia, è senza parametri. Dall'osservazione dello smontaggio, ciò che accade è che il compilatore capisce che non è necessario passare x a run() poiché il suo valore è noto al momento della compilazione.

se cambio il codice in questo modo:

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

} 

Il costruttore che viene generato è ora:

constructor : A$1(int) 

L'unico argomento è il valore di x.

27

In questo caso, è perché 100 è una costante. Questo viene cotto nella tua classe.

Se si cambia x di essere:

final int x = args.length; 

... poi vedrete Test$1(int) nell'output. (Questo è nonostante non sia esplicitamente dichiarato E sì, catturando più variabili aggiunge parametri al costruttore..)

+1

@Bohemian: Dato che conosco l'origine della domanda, penso che sia :) –