Можно ли получить ссылку на метод Java, чтобы вызвать его позже? - PullRequest
7 голосов
/ 07 января 2010

Можно ли получить ссылки на методы объекта? Например, я хотел бы иметь метод, который вызывает другие методы в качестве обратных вызовов. Что-то вроде:

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

  }
}

Возможно ли это?

РЕДАКТИРОВАТЬ: я имел в виду методы объекта. Я так понимаю, это невозможно?

Ответы [ 7 ]

7 голосов
/ 07 января 2010

Да, это возможно.

У вас просто есть метод 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
$

Теперь вопрос в том, что вы пытаетесь сделать? возможно, есть лучшие способы. Но на ваш вопрос ответ ДА.

4 голосов
/ 07 января 2010

Java 7 будет иметь замыкания, которые позволят вам сделать это.

Пока это не доступно, у вас есть два варианта

  • Держите ссылку на интерфейс с известным методом и вызывайте этот
  • Используйте рефлексию для вызова метода.
3 голосов
/ 07 января 2010

Вот пример того, что требуется для обратного вызова:

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 в Whwhat.myMethod, он напечатает все, что вы передаете, в качестве аргументов.

3 голосов
/ 07 января 2010

Работает вопреки философии дизайна Java. Вы должны создать класс с одним методом и передать ссылку на его экземпляр.

1 голос
/ 07 января 2010

Хотя это возможно с помощью отражения, гораздо лучше сделать так, чтобы объект передавался через интерфейс, как в настоящее время работает сортировка (передача в компараторе). Принятие привычки думать и проектировать таким образом - это начало реального понимания ОО-программирования.

Выполнение этого с помощью ссылок на методы приводит к ухудшению общего дизайна - но, очевидно, легче для быстрой одноразовой взломать работу. Если вы довольны взломом, просто используйте Groovy, в который встроены все эти ярлыки и который имеет значительно сокращенный / упрощенный синтаксис, предназначенный только для быстрого одноразового кода вместо долгосрочного обслуживания.

1 голос
/ 07 января 2010

Да, вы используете API отражения, например java.lang.Class.getMethods() (и другие подобные методы на Class). Вы вызываете объект Method, используя Method.invoke().

API отражения не особенно приятен в использовании, и он несет в себе снижение производительности (хотя это гораздо менее важно, чем раньше), но он выполняет свою работу.

0 голосов
/ 07 января 2010

С помощью Reflection вы можете получить доступ к методам класса - см.

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);
        }
    }

Будьте осторожны, так как это не будет работать с нулевыми параметрами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...