2012-05-29 11 views
12

¿Hay alguna sintaxis Java para acceder a nuevos métodos definidos dentro de las clases internas anónimas desde la clase externa? Sé que puede haber varias soluciones, pero me pregunto si existe una sintaxis especial.¿Puedo acceder a nuevos métodos en clase interna anónima con alguna sintaxis?

Por ejemplo

class Outer { 

    ActionListener listener = new ActionListener() { 

     @Override 
     void actionPerformed(ActionEvent e) { 
      // do something 
     } 

     // method is public so can be accessible 
     public void MyGloriousMethod() { 
      // viva! 
     } 

    }; 

    public void Caller() { 
     listener.MyGloriousMethod(); // does not work! 
    } 


} 

mi propia solución

Me acabo de mudar todos los métodos y los miembros hasta la clase externa.

Respuesta

18

Una vez que la instancia de la clase anónima se ha convertido implícitamente en el tipo con nombre, no se puede devolver porque no hay un nombre para el tipo anónimo. Puede acceder a los miembros adicionales de la clase interna anónima a través del this dentro de la clase, en la expresión inmediata después de la expresión y el tipo puede inferirse y devolverse mediante una llamada a un método.

Object obj = new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
    @Override public String toString() { 
     fn(); 
     return ""; 
    } 
}; 
obj.toString(); 



new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
}.fn(); 


identity(new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
}).fn(); 
... 
private static <T> T identity(T value) { 
    return value; 
} 
+0

¡Guau! ¡Ya conoce el caso cuando se puede llamar a un miembro de la clase anónima! –

3

Su interlocutor conoce listener como ActionListener y, por lo tanto, no sabe nada sobre ese nuevo método. Creo que la única manera de hacer esto (aparte de hacer gimnasia de reflexión, lo que realmente frustraría el propósito de usar una clase anónima, es decir, acceso directo/simplicidad) es simplemente subclase ActionListener y no usar una clase anónima.

+0

Sip. La solución aquí es ... no la hagas anónima. –

+0

@Louis si no lo hago anónimo, no ganaré con la economía de sintaxis. Tendré que crear una clase y una instancia de la misma. –

+0

@SuzanCioc: También crea una clase y una instancia de la misma con el código actual. La clase es anónima, pero es la única diferencia. –

1

No, es imposible. Tendría que convertir el ActionListener en su nombre real de subclase, pero como es anónimo, no tiene un nombre.

+0

Pero podrían crear una palabra clave para esto como 'listener.that.MyGloriousMethod()' o '((Anónimo) listener) .MyGloriousMethod()' dado que la clase anónima no es en realidad anónima para JVM, sino solo su nombre desconocido para el programador y entonces el problema es solo denotarlo de alguna manera. –

+0

Podrían haber imaginado algo, pero no lo hicieron, porque ya es factible: creando una clase interna no anónima. –

1

La forma correcta de hacerlo es usando la reflexión:

import java.lang.reflect.InvocationTargetException; 

public class MethodByReflectionTest { 

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { 

     Object obj = new Object(){ 
      public void print(){ 
       System.out.println("Print executed."); 
      } 
     }; 

     obj.getClass().getMethod("print", null).invoke(obj, null); 
    } 
} 

Puede comprobar aquí: How do I invoke a Java method when given the method name as a string?

5

Un estudiante en mi clase preguntó nuestro profesor si esto se podría hacer el otro día . Aquí está lo que escribí como una prueba fresca del concepto que se puede hacer, aunque no vale la pena, en realidad es posible y aquí es cómo:

public static void main(String[] args){ 

    //anonymous inner class with method defined inside which 
    //does not override anything 
    Object o = new Object() 
    { 
     public int test = 5; 
     public void sayHello() 
     { 
      System.out.println("Hello World"); 
     } 
    }; 

    //o.sayHello();//Does not work 

    try 
    { 
     Method m = o.getClass().getMethod("sayHello"); 
     Field f = o.getClass().getField("test"); 
     System.out.println(f.getInt(o)); 
     m.invoke(o); 
    } catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

Al hacer uso de la clase Método de Java podemos invocar un método pasando el valor de cadena y los parámetros del método. Lo mismo se puede hacer con los campos.

¡Pensé que sería genial compartir esto!

0

Sí se puede acceder al método de ver el siguiente ejemplo en caso de duda por favor comentar

package com; 
interface A 
{ 
    public void display(); 
} 
public class Outer { 
    public static void main(String []args) 
    { 
     A a=new A() { 
     @Override 
     public void display() { 
      System.out.println("Hello"); 
     } 
    }; 
     a.display(); 
    } 
    } 
Cuestiones relacionadas