2011-12-20 29 views
6

estoy pasando una interfaz como aplicación anónimo a un objeto diferente como esto:cruce de clase anónima

public interface Interface { 
    public int convert (int a); 
} 



public static void main(String[] args) throws IOException, InterruptedException { 

    final int[] array = {1,6,3,5,7,8,4,0,3}; 
    Interface inter = new Interface() {   
     public int convert(int a) { 
     int result = a;     
     for (int i = 0; i < array.length; i++) { 
     a=a+array[i]; 
     }    
     return a; 
     } 
    }; 

    SomeObject ty = new SomeObject(); 
    ty.Test(7, inter); 
} 

public class SomeObject { 

    public void Test(int number, Interface inter) {    
    System.out.println(inter.convert(number)); 
    } 
} 

Mi pregunta es: ¿cómo funciona? ¿Cómo sabe SomeObject acerca de la matriz que no se pasa directamente al objeto (matriz no es miembro de la clase anónima).

actualización
(lo siento para finales de actualización)

lo vars sobre el miembro o los métodos de los métodos que se utilizan en la clase anónima? que no son finales

Interface inter = new Interface() {    
      public int convert(int a) { 
      int result = a + someMemberVar;     
      for (int i = 0; i < array.length; i++) { 
      a=a+array[i]; 
      }    
      return a; 
      } 
     }; 
+1

¿Cuál es el propósito de la línea 'int result = a;'? –

Respuesta

2

Mi pregunta ¿cómo funciona? Cómo sabe SomeObject sobre la matriz que no se pasa directamente al objeto (la matriz no es miembro de la clase anónima).

  • Respuesta: No lo hace; a menos que declare array como final.
  • Razonamiento: Funciona (si la matriz es definitiva) porque, como es definitiva, se puede tratar como una constante, ya que la función anónima sabe que no se puede cambiar la matriz.

lo que sobre el miembro VARs o métodos métodos que se utilizan en la clase anónima ? que no son finales

  • Respuesta: Las variables de instancia y métodos (así como las variables y métodos estáticos) están en el alcance de todos modos, cuando se crea la clase anónima.
+0

sí, es final. lo siento – omrid

+0

por lo que toda la matriz en su estado actual pasó a SomeObject como constante? – omrid

+1

Solo se pasa una referencia al objeto de matriz a la clase anónima. Si el método de declaración cambió los elementos de la matriz *, la clase anónima lo vería. –

2

Dado que, la variable local del método se declara directamente dentro de un bloque de método, solo es visible dentro del método, a partir de la siguiente instrucción después de su declaración. Y me refiero a la variable que se declara dentro del método pero fuera de cualquier otro bloque (por ejemplo, while { /* not here */ }) que pueda aparecer dentro de ese método.

Y si ve, su clase anónima también se define como una clase local dentro del mismo método después de la declaración array. Es por eso que es visible para la clase.

La razón por la que usted necesita para hacer arrayfinal para poder utilizarlo dentro de la clase anónima es que las variables locales viven sólo hasta las vidas de método, pero el objeto de la clase local podrían vivir más tiempo (incluso después de que se realiza el método)

+0

La visibilidad en realidad también está limitada por bloques. Por lo tanto, no son variables locales dentro de un método, sino que también deben estar dentro del mismo bloque. – Stefan

+0

@Stefan: Eso es correcto. –

+0

@Stefan: Gracias. Se modificó de local a method-local. –

0

Está pasando la interfaz objeto que tiene acceso a la matriz en el método SomeObject.

So SomeObject está utilizando el mismo objeto Interface que pasó en main.

Dado que la interfaz tiene acceso a la matriz, es posible usarla.

No es SomeObject que está utilizando la matriz. Es un objeto de interfaz.

+0

Las clases anónimas tienen acceso a las variables finales de sus métodos adjuntos – pringi

0

Java mantiene una referencia a todos los objetos (finales) de la clase adjunta utilizada en la clase interna. Si usted quiere saber cómo este truco es criada, añadir la siguiente línea al Método de ensayo:

System.out.println(inter.getClass().getDeclaredConstructors()[0].getParameterTypes()[0].getCanonicalName() 

y su salida será "int []"

Así, el simple compilador crea un constructor para la clase interna y pasarle los campos que necesita

+0

ya he agregado la final al código :) – omrid

+0

elimino las cosas relacionadas finales –

1

Esto forma parte de las reglas de visibilidad y visibilidad para Java. En su ejemplo actual se llama Closure. Básicamente todo lo que se define en un bloque es visible dentro de ese bloque. Por ejemplo este es el código de Java válida (en cualquier lugar en un método):

{ 
    final int i = 5; 
    // do somthing with i 
} 
// cant refernce i here 
{ 
    final int i = 6; 
    // do somthing with i 
} 
// cant refernce i here 

Dado que se define una nueva clase dentro del bloque (i wouldnt trabajo si sólo instanciado ella) se ve todo lo declarado en el mismo bloque. El único límite que Java le otorga es que no puede cambiar el valor después de la primera asignación, para evitar problemas cuando la referencia 'escapa' de su bloque (multihilo, vive más tiempo que el bloque declarante, etc.). Si declaras los parámetros del método final, también puedes usarlos porque están definidos dentro del mismo bloque.

Así que si ha cambiado su código a este

 { 
      final int[] array = {1,6,3,5,7,8,4,0,3}; 
     } 
     Object inter = new Object() 
     {   
      public void test() 
      { 
       System.out.println(array); 
      } 
     }; 

No funcionaría (probarlo).

Cuestiones relacionadas