2011-05-19 20 views
7

Estoy tratando de medir el tiempo de ejecución para varios métodos. así que estaba pensando en hacer un método en lugar de duplicar el mismo código muchas veces.¿Puedo pasar un Método como parámetro de otro método en Java?

Aquí está mi código:

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

Supongamos que tengo myMethod(), ¿cómo se puede usar I MeasureExecutionTime() para medir el tiempo de ejecución myMethod 's?

Respuesta

4

métodos no son objetos de primera clase en Java, por lo que no se pueden pasar como parámetros. Puedes usar wrap your method call en una clase anómala que se extiende, p. la interfaz Runnable:

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

... 


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

Ver java.lang.reflect.Method. –

5

la forma más sencilla de hacer esto es pasar de una interfaz. Algo así como

public interface CommonFuncs { 

    public void execute(); 
    ... more functions 

} 

y luego en usted puede tener métodos que toman CommonFuncs como argumento. Las implementaciones de esos métodos pueden llamar al método execute.

2

Estoy de acuerdo con @hvgotcodes, pero sí, es posible, aunque no se llama a ella como m(), pero utilizando invoke (lo que significa que probablemente debería pasar a otro argumento o dos con eso...).

2

Usted está en el camino correcto, que necesita para aprobar el método objeto, el objeto de destino en que desea ejecutar el método y los argumentos que se necesita y luego invocarlo en su intento de captura, algo así como:

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."); 
} 
1

que tienen un contador llamada a un objeto que básicamente es el siguiente:

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

Con dos métodos de "tiempo" para cronometrar métodos que devuelven algo y otros métodos que son nulas.

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

yo decidimos volver a lanzar las excepciones como excepciones de tiempo de ejecución (ya que no soy un fan de excepciones comprobadas) pero del mismo modo que podría hacer que su MyRunnable encargo excepciones tiro interfaz y simplemente coger y volver a lanzar ellos. Aquí hay un uso de lo anterior:

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

O esto, en el caso del valor de regresar:

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

me gusta esto porque mis objetos de contador pueden estar expuestos durante JMX y se inyecta donde los necesito. Podrías hacer lo que pediste con reflexión, pero creo que sería complicado (en mi humilde opinión).

1

puede hacer algo bajo como:

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."); 
} 
Cuestiones relacionadas