Can I pass a Method as parameter of another method

2020-03-01 18:20发布

I am trying to measure the execution time for several methods. so I was thinking to make a method instead of duplicate same code many times.

Here is my code:

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

Suppose I have myMethod(), how can I use MeasureExecutionTime() to measure myMethod's execution time?

6条回答
乱世女痞
2楼-- · 2020-03-01 18:55

the simplest way to do this is to pass an interface. So something like

public interface CommonFuncs {

   public void execute();
   ... more functions

}

and then in you can have methods that take CommonFuncs as an argument. The implementations of those methods can call the execute method.

查看更多
Lonely孤独者°
3楼-- · 2020-03-01 18:57

I have a object call Counter which basically looks like this:

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

With two "time" methods for timing methods that return something and other methods which are void.

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

I chose to rethrow the exceptions as runtime exceptions (as i'm not a fan of checked exceptions) but you could just as well make your custom MyRunnable interface throw exceptions and just catch and re-throw them. Here's a usage of the above:

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

Or this, in the returning-value case:

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

I like this because my counter objects can be exposed over JMX and injected wherever i need them. You could do what you've asked with reflection, but i think that would be messy (IMHO).

查看更多
仙女界的扛把子
4楼-- · 2020-03-01 18:59

You are in the correct path, you need to pass the Method object, the target object on which to execute the method and the arguments it takes and then invoke it into your try catch, something like:

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.");
}
查看更多
疯言疯语
5楼-- · 2020-03-01 18:59

you may do smth like:

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.");
}
查看更多
兄弟一词,经得起流年.
6楼-- · 2020-03-01 19:05

Methods aren't first-class objects in Java, so they can't be passed as parameters. You could use wrap your method call in an annoymous class that extends e.g. the Runnable interface:

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

...


MeasureExecutionTime(new Runnable() { public void run() { m(); } });
查看更多
Melony?
7楼-- · 2020-03-01 19:08

I agree with @hvgotcodes, But yes, it is possible, though you don't call it like m(), but using invoke (which means that you probably should pass another argument or two with it...).

查看更多
登录 后发表回答