2011-05-19 64 views
7

我想測量幾種方法的執行時間。所以我正在考慮做一個方法而不是多次重複相同的代碼。我可以傳遞一個Method作爲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的執行時間?

回答

4

方法不是Java中的第一類對象,因此它們不能作爲參數傳遞。您可以使用將您的方法調用包裝在一個令人煩惱的類中,例如擴展在Runnable接口:

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

... 


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

見java.lang.reflect.Method中。 – 2011-05-19 15:45:12

5

最簡單的方法是通過一個接口。所以像

public interface CommonFuncs { 

    public void execute(); 
    ... more functions 

} 

然後在你可以有方法,把CommonFuncs作爲參數。這些方法的實現可以調用execute方法。

2

我同意@hvgotcodes,但是,是的,它是可能的,儘管你不把它像m(),但使用invoke(這意味着你應該通過另外一個參數或兩個與它...)。

2

你是在正確的路徑,你需要傳遞的Method對象,在其上執行的方法,它需要的參數,然後調用到您嘗試捕捉目標對象,是這樣的:

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

我有一個對象調用計數器基本上是這樣的:

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

我選擇重新拋出異常的運行時異常(如我不是checked異常的粉絲),但你也可以同樣讓您的自定義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和注射的地方,我需要他們。你可以用反射來做你所要求的,但我認爲這會很麻煩(恕我直言)。

1

你可以做像水木清華:

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."); 
} 
相關問題