2012-05-29 27 views
12

有沒有任何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! 
    } 


} 

自己的解決方案

我剛移動的所有方法和成員最多外部類。

回答

18

一旦匿名類實例被隱式轉換爲指定類型,它就不能被退回,因爲匿名類型沒有名稱。您可以通過類中的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> T identity(T value) { 
    return value; 
} 
+0

哇!你知道匿名類成員可以被調用的情況! –

3

您的來電者知道listenerActionListener,因此它不知道任何關於該新方法的信息。我認爲唯一能做到這一點的方法(除了做反射體操,這實際上會破壞使用匿名類的目的,即快捷/簡單),只是簡單地劃分子類ActionListener而不使用匿名類。

+0

是啊。這裏的解決方案是......不要匿名。 –

+0

@Louis如果我不使它匿名我不會從語法經濟中獲益。我需要創建一個類和它的一個實例。 –

+0

@SuzanCioc:您還可以使用當前代碼創建一個類及其實例。這個班是匿名的,但這是唯一的區別。 –

1

不,這是不可能的。您需要將ActionListener轉換爲其真實的子類名稱,但由於它是匿名的,因此它沒有名稱。

+0

但是他們可以爲'this listener.that.MyGloriousMethod()'或'((匿名)偵聽器)創建一些關鍵字.MyGloriousMethod()'因爲匿名類實際上並不是JVM的匿名類型,只是程序員不知道它的名字,所以問題只是以某種方式表示它。 –

+0

他們可能已經想象出一些東西,但他們沒有,因爲它已經非常簡單地實現了:通過創建一個非匿名的內部類。 –

1

做正確的方法是使用反射:

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

您可以點擊這裏:How do I invoke a Java method when given the method name as a string?

5

在我班上一個學生問我的教授是否可以這樣做前些天。下面是我寫的是觀念的一個很酷的證據證明它可以做到的,但不值得的,它實際上是可能的,這裏是如何:

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的方法類的,我們可以調用的方法通過傳入方法的字符串值和參數。領域也可以做同樣的事情。

只是覺得這將是很酷分享!

0

是的,你可以訪問方法請參見下面的例子,如果有任何疑問,請發表評論

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(); 
    } 
    } 
相關問題