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