簡體   English   中英

我可以使用某種語法在匿名內部類中訪問新方法嗎?

[英]Can I access new methods in anonymous inner class with some syntax?

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

我班上的一位學生問我們的教授是否有一天可以做到這一點。 這是我寫的一個很酷的概念證明,盡管不值得,但實際上是可以做到的,這是可以做到的,這是如何做到的:

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 ,因此對該新方法一無所知。 我認為,做到這一點的唯一方法(除了進行反射體操之外,這實際上會破壞使用匿名類(即,快捷方式/簡單性)的目的)只是對ActionListener進行子類化而不使用匿名類。

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

正確的方法是使用反射:

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方法?

有趣的是,現在可以使用var結構(Java 10或更高版本)來實現。 例:

var calculator = new Object() {
  BigDecimal intermediateSum = BigDecimal.ZERO;
  void calculate(Item item) {
    intermediateSum = Numbers.add(intermediateSum, item.value);
    item.sum= intermediateSum;
  }
};
items.forEach(calculator::calculate);

這里帶有方法參考,但是當然也適用於點方法調用。 它也適用於字段。 享受新的Java。 :-)

我在這里找到了有關var和匿名類的更多技巧: https : //blog.codefx.org/java/tricks-var-anonymous-classes/

是的,如果您有任何疑問,請訪問下面的示例,請發表評論

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM