Можно ли получить ссылку на метод Java, чтобы вызвать его позже?
можно ли получить ссылки на методы объекта? Например, я хотел бы иметь метод, который вызывает другие методы в качестве обратных вызовов. Что-то вроде:
public class Whatever
{
public void myMethod(Method m,Object args[])
{
}
}
это возможно?
EDIT: я имел в виду методы объекта. Я так понимаю, это невозможно?
7 ответов
Да, это возможно.
у вас просто есть метод get и вызвать его.
вот пример кода:
$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
$
теперь вопрос в том, что вы пытаетесь сделать? возможно, это лучший способ. Но что касается твоего вопроса, то ответ-да.
Java 7 будет иметь замыкания, которые позволят вам это сделать.
пока это не доступно у вас есть два варианта
- удерживайте ссылку на интерфейс с известным методом и вызовите это
- используйте отражение для вызова метода.
противоречит философии дизайна Java. Вы должны создать класс с одним методом и передать ссылку на экземпляр этого.
вот пример того, что требуется для звонка:
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, он будет печатать все, что вы передаете в качестве аргументов.
Да, вы используете API отражения, например java.lang.Class.getMethods()
(и другие подобные методы на Class
). Вы вызываете Method
объект с помощью Method.invoke()
.
API отражения не особенно приятно использовать, и он несет штраф за производительность (хотя это гораздо менее существенно, чем раньше), но он выполняет эту работу.
хотя это возможно через отражение, гораздо лучше передать объект и получить к нему доступ через интерфейс, как сортировка в настоящее время работает (передача в компараторе). Привыкание думать и проектировать таким образом-это начало реального понимания программирования ОО.
делать это через ссылки на методы приводит к худшему общему дизайну-но, очевидно, проще для быстрой одноразовой работы Хака. Если вы довольны взломом, просто используйте Groovy где все эти короткие сокращения встроены и имеют значительно сокращенный/упрощенный синтаксис, предназначенный только для быстрого одноразового кода вместо долгосрочного обслуживания.
через отражение вы можете получить доступ к методам класса-см.
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);
}
}
будет однако будьте осторожны, так как это не будет работать с нулевыми параметрами.