2012-05-29 2 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

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

+0

ЮП. Решение здесь ... не делает его анонимным. –

+0

@Louis, если я не сделаю его анонимным, я не выиграю от экономии синтаксиса. Мне нужно будет создать класс и экземпляр его. –

+0

@SuzanCioc: вы также создаете класс и экземпляр его с текущим кодом. Класс анонимный, но это единственное отличие. –

1

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

+0

Но они могут создать некоторое ключевое слово для этого типа '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(); 
    } 
    } 
Смежные вопросы