Действительно ли возможно заставить ссылку на метод Java вызвать его позже?

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

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

  }
}

Действительно ли это возможно?

Править: Я имел в виду методы объекта. Я беру его, это не возможно?

7
задан Geo 6 January 2010 в 21:33
поделиться

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
$

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

7
ответ дан 6 December 2019 в 10:00
поделиться

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

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

3
ответ дан 6 December 2019 в 10:00
поделиться

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

3
ответ дан 6 December 2019 в 10:00
поделиться

С помощью отражения можно получить доступ к методам класса - см.

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

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

0
ответ дан 6 December 2019 в 10:00
поделиться

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

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

1
ответ дан 6 December 2019 в 10:00
поделиться

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

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

1
ответ дан 6 December 2019 в 10:00
поделиться

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

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

  • Удерживайте ссылку на интерфейс с известным включенным методом и вызывайте, что
  • Использовать отражение для вызова метода.
4
ответ дан 6 December 2019 в 10:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: