我可以使用一些语法访问匿名内部类中的新方法吗?

是否有任何Java语法来访问外部类中匿名内部类中定义的新方法? 我知道可以有各种变通方法,但我想知道是否存在特殊语法?

例如

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! } } 

我自己的解决方案

我刚把所有的方法和成员都移到了外层。

一旦匿名类实例被隐式转换为命名类型,就无法将其强制转换,因为匿名类型没有名称。 您可以在类中通过this方法访问匿名内部类的其他成员,在表达式之后的表达式中,可以通过方法调用推断并返回类型。

 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 identity(T value) { return value; } 

我class上的一名学生问我们的教授前几天是否可以这样做。 以下是我作为一个很好的概念certificate,它可以完成,虽然不值得,它实际上是可能的,这是如何:

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

通过使用Java的Method类,我们可以通过传入方法的字符串值和参数来调用方法。 用字段可以做同样的事情。

只是觉得分享这个会很酷!

您的调用者将listener知道为ActionListener ,因此它不知道有关该新方法的任何信息。 我认为这样做的唯一方法(除了做reflection体操,这实际上会破坏使用匿名类的目的,即快捷/简单)是简单地ActionListener而不使用匿名类。

不,这是不可能的。 您需要将ActionListener强制转换为其真正的子类名称,但由于它是匿名的,因此它没有名称。

正确的方法是使用reflection:

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

您可以在此处查看: 如果将方法名称指定为字符串,如何调用Java方法?

是的,您可以访问该方法,如果有任何疑问请参阅下面的示例请注释

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