Могу ли я передать метод как параметр другого метода в java?

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

вот мой код:

private void MeasureExecutionTime(Method m)
{
    startTime = System.nanoTime();
    try
    {
        m();
    }
    finally
    {
        endTime = System.nanoTime();
    }
    elapsedTime = endTime - startTime;
    System.out.println("This takes " + elapsedTime + " ns.");
}

предположим, что я myMethod(), Как я могу использовать MeasureExecutionTime() измерения myMethodвремя выполнения?

6 ответов


методы не являются первоклассными объектами в Java, поэтому они не могут быть переданы как параметры. Вы можете использовать обертывание вызова метода в раздражающем классе, который расширяет, например,Runnable интерфейс:

private void MeasureExecutionTime(Runnable r) {
    r.run();
}

...


MeasureExecutionTime(new Runnable() { public void run() { m(); } });

самый простой способ сделать это-передавать интерфейс. Что-то вроде

public interface CommonFuncs {

   public void execute();
   ... more functions

}

и тогда у вас могут быть методы, которые принимают CommonFuncs в качестве аргумента. Реализации этих методов могут вызывать execute метод.


Я согласен с @hvgotcodes, Но да, это возможно, хотя вы не называете это как m(), но через invoke (что означает, что вы, вероятно, должны передать с ним еще один или два аргумента...).


вы находитесь в правильном пути, вам нужно передать объект метода, целевой объект, на котором выполняется метод и аргументы, которые он принимает, а затем вызвать его в свой try catch, что-то вроде:

private void MeasureExecutionTime(Method m, Object target, Object args) 
                            throws IllegalArgumentException, 
                                   IllegalAccessException, 
                                   InvocationTargetException
{
    long startTime = System.nanoTime();
    long endTime;
    try
    {
        m.invoke(target, args);
    }
    finally
    {
        endTime = System.nanoTime();
    }
    long elapsedTime = endTime - startTime;
    System.out.println("This takes " + elapsedTime + " ns.");
}

у меня есть счетчик вызовов объектов, который в основном выглядит так:

private long count;
private long errors;
private long duration;
private long errorDuration;

С двумя "время" методы синхронизации, которые возвращают что-то и другие методы, которые являются недействительными.

public <T> T time(ReturningRunnable<T> runnable) {
    long start = currentTimeMillis();
    T result = null;
    try {
        result = runnable.run();
    } catch (Throwable ex) {
        errorDuration += currentTimeMillis() - start;
        errors++;
        throw runtime(ex);
    }
    duration += currentTimeMillis() - start;
    count++;
    return result;
}

public void time(Runnable runnable) {
    time(new RunnableRunner(runnable));
}

Я решил переосмыслить исключения как исключения во время выполнения (поскольку я не поклонник проверенных исключений), но вы также можете сделать свой пользовательский интерфейс MyRunnable исключениями и просто поймать и повторно бросить их. Вот использование вышеизложенного:

counter.time(new Runnable() {
    @Override
    public void run() {
        // Do something
    });

или это, в случае возвращаемого значения:

return counter.time(new ReturningRunnable<Integer>() {
    @Override
    public Integer run() {
        return 1; // You get the idea
    });

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


вы можете сделать что-то вроде:

private void MeasureExecutionTime(Method m)
{

    startTime = System.nanoTime();
    try
    {
        m.invoke(classObj, args);
    }
    finally
    {
        int endTime = System.nanoTime();
    }
    elapsedTime = endTime - startTime;
    System.out.println("This takes " + elapsedTime + " ns.");
}