有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

反射接收Java方法而不使用getDeclaredMethod

我希望将子类中的java方法数组初始化为类字段,如下所示

void callme() {System.out.println("hi!");}
Method[] actions = new Method[] {&callme,&callme};

并在父类处调用此数组中的所有方法,如下所示:

for (meth:actions) {meth.invoke();}

但是,目前我找不到一种方法来隐式初始化actions数组,而不是通过构造函数。以下是由于未处理的异常而导致的错误:

Method[] actions = new Method[] {
    this.getClass().getDeclaredMethod("count")
};

如上所述,在将此数组显式初始化为字段而不是构造函数时,我无法捕获异常

我是java reflection的新手,所以这可能是一个显而易见的问题,但我在google上找不到答案,任何帮助都将不胜感激

谢谢

附言

正如下面Scott所猜测的,我“希望超类调用子类中定义的特定方法集”


共 (6) 个答案

  1. # 1 楼答案

    你确定反思是正确的吗?通常,一个带有几个匿名类的接口实现它会更好

    您可以编写一个初始化程序块,以便在初始化期间捕获异常

    为什么不使用getMethod()

  2. # 2 楼答案

    我可以从你的符号看出,你是在用C思考。在java中,我们并没有真正使用指向函数的指针

    一般来说,您不会为此使用java反射。正如其中一张海报所说,您可以创建一个接口,并拥有实现该接口的对象,或者直接实现该接口,或者使用适配器或匿名类:

    interface Callable { void callme(); }
    
    Callable[] foo = new Callable[] {
      new Callable() { public void callme() {System.out.println("foo!");}},
      new Callable() { public void callme() {System.out.println("bar!");}}
    };
    
    for(Callable c: foo) {
      c.callme();
    }
    
  3. # 3 楼答案

    只要你的方法真的在本文中声明了,它就应该工作得很长。getClass()。 如果是继承的,则应使用类。取而代之的是getMethod()

    然而,在java中,不使用函数指针,而是使用想要调用的方法定义一个接口,并让该接口由目标对象实现

    也考虑使用ARAYLIST或其他集合类而不是数组。

  4. # 4 楼答案

    看看Apache Commons - Beanutils!它就像一个包裹着所有反射的东西,非常容易使用。它包装了方法调用、修改属性、查找

    如果你想把动态引入Java,你应该看看一个动态JVM语言,它可以被简单的Java应用程序使用。jar图书馆!其中一个是Groovy,它包含java语法,并引入了许多动态功能(脚本、快速原型、元对象协议、运行时方法修复、动态代理等等)

  5. # 5 楼答案

    在类中创建一个静态方法,该方法将返回一个声明的方法数组,并正确处理异常

    private static Method[] declaredMethods(Class<T> clazz, String methodName) {
      Method[] result = new Method[1];
      try{
        result[0] = clazz.getDeclaredMethod(methodName);
      } catch (NoSuchMethodException nsme) {
        // respond to the error
      } catch (SecurityException se)  {
        // Respond to the error
      }
    
      return result;
    }
    
    Method[] actions = declaredMethods("count");
    
  6. # 6 楼答案

    [注:下面的代码尚未编译,但应该能让人理解]

    我应该回应一下——你想实现什么

    如果想让一个超类调用子类中定义的一组特定方法,可以做几件事

    对于反射,我建议使用注释:

    1)定义注释HeySuperclassCallMe(确保在运行时保留)

    2)注释要使用HeySuperclassCallMe调用的方法

    @HeySuperclassCallMe public void foo...
    

    3)在你的超类中执行以下操作

    for (Method m : getClass().getMethods())
      if (m.getAnnotation(HeySuperclassCallMe.class) != null)
         m.invoke(...)
    

    这是一种很好的反思方式

    对于非反射(应该快一点,但代码更多):

    1)定义一个表示调用的接口

     public interface Call {
         void go();
     }
    

    2)在超类中定义

     private List<Call> calls
     protected void addCall(Call call)
    

    3)在子类中,使用addCall:

     addCall(new Call() {public void go() {foo();}} );
    

    4)在超类中

     for (Call call : calls)
        call.go();