English 中文(简体)
不使用getDeclaredMethod接收Java方法
原标题:
  • 时间:2009-03-13 12:50:42
  •  标签:

我希望在子类中初始化一个Java方法的数组作为类字段,如下所示。

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

并在父类中这样调用该数组中的所有方法:

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

然而目前我找不到一种隐式初始化操作数组的方法,而不是通过构造函数。以下操作会因为未处理的异常而导致错误:

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

就如前面所述,当以字段形式显式初始化数组,而非在构造函数中时,我无法捕获异常。

我是Java反射的新手,所以这可能是一个很明显的问题,但我在谷歌上找不到答案,任何帮助将不胜感激。

谢谢 (xiè xiè)

P.S. (附言)

正如下面的Scott所猜测的那样,我“想要一个超类调用在子类中定义的特定一组方法”。

最佳回答

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

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");
问题回答

你确定反射是正确的做法吗?通常,具有多个匿名类实现接口的接口会更好的样式。

你可以编写一个初始化块以在初始化过程中捕获异常。

你为什么不使用 getMethod() 方法?

[注意:下面的代码尚未编译,但应该能够传达出其意思]

我应该回响——你想要实现什么?

如果您希望超类调用子类中定义的特定方法集合,可以采取一些措施。

带有反射,我建议使用注释:

1)定义一个注释HeySuperclassCallMe(确保保留为RUNTIME)。

2) 用“HeySuperclassCallMe”注释要调用的方法

@HeySuperclassCallMe public void foo...

3)在您的超级类中进行如下操作

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

那是一个不错的反思方式来做到这一点。

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

定义一个表示调用的接口

 public interface Call {
     void go();
 }

2)在您的超类中,定义一个方法

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

3)在子类中,使用addCall:

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

在超类中

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

看看Apache Commons - Beanutils吧!它就像是一个包装器,包装了所有反射,非常易于使用。它包装方法调用、修改属性、查找等等...

如果您想给Java带来动态特性,您应该查看可以通过简单包含.jar库使用的动态JVM语言!其中之一是Groovy,它包含java语法并带来了许多动态功能(脚本编写,快速原型设计,元对象协议,运行时方法替换,动态代理...)。

This should work as long, as your method is really declared in in the this.getClass(). If it is inherited, you should use Class.getMethod() instead.

然而,在Java中,我们可以通过定义一个接口来调用需要调用的方法,然后让该接口被目标对象实现,而不是使用函数指针。

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

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




相关问题
热门标签