Могу ли я передать метод как параметр другого метода в 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.");
}