Подтвердить что ты не робот

Могу ли я получить доступ к новым методам в анонимном внутреннем классе с некоторым синтаксисом?

Есть ли какой-либо синтаксис 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!
    }


}

МОЕ СОБСТВЕННОЕ РЕШЕНИЕ

Я просто переместил все методы и члены в внешний класс.

4b9b3361

Ответ 1

После того как экземпляр анонимного класса был неявным образом внесен в именованный тип, он не может быть отброшен, потому что нет имени для анонимного типа. Вы можете получить доступ к дополнительным членам анонимного внутреннего класса через 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;
}

Ответ 2

Студент в моем классе спросил нашего профессора, можно ли это сделать на днях. Вот что я написал как замечательное доказательство концепции, что это можно сделать, хотя это и не стоит того, что на самом деле возможно, и вот как это сделать:

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, мы можем вызывать метод, передавая строковое значение и параметры метода. То же самое можно сделать с полями.

Просто подумал, что было бы круто поделиться этим!

Ответ 3

Ваш вызывающий абонент знает listener как ActionListener, и поэтому он ничего не знает об этом новом методе. Я думаю, что единственный способ сделать это (кроме того, что делать рефлекторную гимнастику, которая действительно могла бы победить цель использования анонимного класса, т.е. Ярлыка/простота), - это просто подкласс ActionListener и не использовать анонимный класс.

Ответ 4

Нет, это невозможно. Вам нужно будет указать ActionListener на его настоящее имя подкласса, но поскольку он анонимный, он не имеет имени.

Ответ 5

Правильный способ сделать это - использовать отражение:

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 при указании имени метода в виде строки?

Ответ 6

Забавно, но теперь это разрешено с помощью конструкции 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/

Ответ 7

Да, вы можете получить доступ к методу в приведенном ниже примере, если есть сомнения, пожалуйста, прокомментируйте

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