在不使用getDeclaredMethod的情况下接收Java方法

在不使用getDeclaredMethod的情况下接收Java方法,java,reflection,initialization,Java,Reflection,Initialization,我希望将子类中的java方法数组初始化为类字段,如下所示 void callme() {System.out.println("hi!");} Method[] actions = new Method[] {&callme,&callme}; 并在父类处调用此数组中的所有方法,如下所示: for (meth:actions) {meth.invoke();} 但是,目前我找不到一种方法来隐式初始化actions数组,而不是通过构造函数。以下是由于未处理的异常而导致的错误:

我希望将子类中的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所猜测的,我“希望一个超类调用子类中定义的一组特定方法”。

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


如果您想将动态引入Java,您应该看看simple可以使用的动态JVM语言,包括一个.jar库!其中一个是包含java语法并引入大量动态功能(脚本、快速原型、元对象协议、运行时方法修复、动态代理…)。

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

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


为什么不使用getMethod()?

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

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");
私有静态方法[]declaredMethods(类clazz,字符串methodName){
方法[]结果=新方法[1];
试一试{
结果[0]=clazz.getDeclaredMethod(methodName);
}捕获(NoSuchMethodException nsme){
//回应错误
}捕获(安全异常se){
//回应错误
}
返回结果;
}
方法[]行动=公布方法(“计数”);

只要您的方法是在This.getClass()中声明的,它就可以正常工作。 如果是继承的,则应改用Class.getMethod()

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


也可以考虑使用ARAYLIST或其他集合类来代替数组。

[注释:下面的代码没有被编译,但是应该跨出这个想法]

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

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

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

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)
4) 在超类中

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

我可以从你的符号看出你是在用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();
}

那会有用的,但这就像。。。嗯,尽管Java有时很丑陋;-)没有人能阻止您在单独的类中使用私有构造函数声明静态方法declareMethods(Class clazz,String),并隐藏所有丑陋的细节。更好的是,您可以使用一些Apache Commons库。您可以将methodName设置为varargs。您到底想做什么?正如下面Scott猜测的那样,我试图“如果您希望超类调用子类中定义的特定方法集”,我想到了注释技术,但我不喜欢它,您不能指定顺序。事实上,我最终做到了@UseMessage(order=0)。这很好,但很难看。(而且更难维护,因为无法在两者之间轻松插入方法)。顺便说一句:如果您将属性命名为“value”,则可以在不使用属性名称的情况下使用它:@UseMessage(0)。不过,这并不能帮助订购。
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();
}