是否有可能获得对Java方法的引用以便稍后调用它?

时间:2010-01-06 21:19:01

标签: java methods

是否可以获取对象方法的引用?例如,我想要一个调用其他方法作为回调的方法。类似的东西:

public class Whatever
{
  public void myMethod(Method m,Object args[])
  {

  }
}

这可能吗?

编辑:我的意思是对象的方法。我认为这是不可能的?

7 个答案:

答案 0 :(得分:7)

是的,有可能。

您只需获取方法并调用它即可。

以下是一些示例代码:

$cat InvokeMethod.java  
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class InvokeMethod {

    public static void invokeMethod( Method m , Object o ,  Object ... args )  
    throws IllegalAccessException, 
           InvocationTargetException {

        m.invoke( o, args );

    }

    public static void main( String [] args ) 
    throws NoSuchMethodException,
           IllegalAccessException,
           InvocationTargetException {

         SomeObject object = new SomeObject();
         Method method = object.getClass().getDeclaredMethod( "someMethod",  String.class );
         invokeMethod( method, object, "World");

    }
}

class SomeObject {
    public void someMethod( String name ){
        System.out.println( "    Hello " + name );
    }
}
$javac InvokeMethod.java 
$java InvokeMethod
Hello World
$

现在问题是,你想做什么?也许是更好的方法。但至于你的问题,答案是肯定的。

答案 1 :(得分:4)

Java 7将有闭包,可以让你这样做。

在此之前,您有两个选择

  • 使用已知方法启用对接口的引用并调用
  • 使用反射来调用方法。

答案 2 :(得分:3)

与Java的设计理念相反。您应该创建一个单方法类并传递对该实例的引用。

答案 3 :(得分:3)

以下是回调所需内容的示例:

public interface Callback {
  public void execute(Object[] args);
}

public class MyCallback implements Callback {
  public void execute(Object args[]) {
    System.out.println(Arrays.asList(args));
  }
}

public class Whatever {
  public void myMethod(Callback callback,Object args[]) {
    callback.execute(args);
  }
}

如果您将MyCallback的一个实例交给Whatever.myMethod,它将打印您提供的任何内容作为参数。

答案 4 :(得分:1)

是的,您使用反射API,例如java.lang.Class.getMethods()(以及Class上的其他类似方法)。您使用Method.invoke()调用Method对象。

反射API使用起来并不是特别好,并且它会带来性能损失(尽管这比以前要少得多),但它确实起到了作用。

答案 5 :(得分:1)

尽管通过反射可以实现,但更好的选择是传递一个对象并通过接口以当前排序的方式访问它(传入比较器)。养成以这种方式思考和设计的习惯是实际理解OO编程的开始。

通过方法参考进行操作会导致更糟糕的整体设计 - 但对于快速的一次性黑客工作来说显然更容易。如果您对黑客行为感到满意,只需使用Groovy,而不是内置所有这些快捷方式,并且具有大大减少/简化的语法,专为快速一次性代码而非长期维护而设计。

答案 6 :(得分:0)

通过反射,您可以访问类的方法 - 请参阅

http://java.sun.com/docs/books/tutorial/reflect/member/methodInvocation.html

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html

但是,您必须传入该类的实例以及参数。你可以创建一个简单的包装类,比如

 class MethodInvoker{
        private Object o;
        private String methodName;
        public MethodInvoker(Object o, String methodName){
            this.o=o;
            this.methodName=methodName;
        }

        public Object invoke(Object[] args) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{
            Class[] paramTypes = new Class[args.length];
            for(int i=0;i<paramTypes.length;i++){
                paramTypes[i] = args[i].getClass();
            }
            return o.getClass().getMethod(methodName, paramTypes).invoke(o, args);
        }
    }

但要小心,因为这不适用于任何null参数。