2010-10-31 18 views
17

Per risolvere un caso di test, è necessario identificare se la funzione è chiamata da una particolare funzione del chiamante. Non posso permettermi di aggiungere un parametro booleano perché spezzerebbe le interfacce definite. Come andare su questo?Java: come ottenere il nome della funzione del chiamante

Questo è ciò che voglio ottenere. Qui non posso modificare i parametri di operation() poiché è un'implementazione dell'interfaccia.

operation() 
{ 
    if not called from performancetest() method 
     do expensive bookkeeping operation 
    ...  

} 
+9

Vorrei sottolineare che in quasi tutte le circostanze questa è davvero una pessima idea. Assicurati di avere davvero una buona ragione prima di implementarla. Considera tutte le possibili alternative. Ad esempio: puoi aggiungere un'interfaccia? –

+0

Ho scoperto un modo senza di esso. Grazie mille per il suggerimento. – devnull

+3

Uno dei motivi per cui questa è una pessima idea è che l'unico approccio di implementazione fattibile sia costoso. –

risposta

54

Si potrebbe provare

StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); 
StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected 
String methodName = e.getMethodName(); 
+2

new Throwable(). FillInStackTrace(). GetStackTrace() [1] .getMethodName() –

+1

@mootinator: Penso che getStackTrace() sia più veloce. – thejh

+1

se correttamente implementati, sono entrambi gli stessi: 'thread.getStackTrace()' fa 'return (new Exception()). GetStackTrace();' se 'thread' è quello corrente. –

0

Ecco una funzione che ho scritto per registrare il nome della funzione della funzione che lo chiama. Esegue la traccia dello stack fino a quando non trova una funzione denominata logIt, quindi visualizza il nome successivo. È un trucco sporco, quindi non farlo se non lo stai usando per eseguire il debug.

private static void logIt() { 
    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); 
    boolean logged = false; 
    boolean foundMe = false; 
    for(int i=0; i<stacktrace.length; i++) { 
     StackTraceElement e = stacktrace[i]; 
     String methodName = e.getMethodName(); 
     if (foundMe) { 
      if (!methodName.startsWith("access$")) { 
       Log.i(TAG, String.format(Locale.US, "%s.%s", e.getClassName(), methodName)); 
       logged = true; 
       break; 
      } 
     } else { 
      if (methodName.equals("logIt")) { 
       foundMe = true; 
      } 
     } 
    } 
    if (!logged) 
     Log.e(TAG, "unlogged call"); 
} 
0

altro campione per l'uso android:

//package your.package.name; 
import android.util.Log; 
/* 
File name: MyDebugLog.java 
*/ 
public class MyDebugLog { 
    private static final int index  = 4;  // <== Index in call stack array 
    private static final String methodName = "Log"; // <== Name of method for public call 
    private static String getCallerName() { 
     String caller = "NONE"; 
     final StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); 
     for (int i = 0; i < stacktrace.length; i++) { 
      Log.e("Method ", "[" + i + "]" + stacktrace[i].getMethodName()); 
     } 
     if (stacktrace.length >= index){ 
      caller = stacktrace[index].getMethodName(); 
     } 
     return caller; 
    } 

    private static String getTag() { 
     String tag = "NONE"; 
     final StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); 
     for (int i = 0; i < stacktrace.length; i++) { 
      Log.e("Method ", "[" + i + "]" + stacktrace[i].getMethodName()); 
      if (stacktrace[i].getMethodName().equals(methodName)) { 
       tag = "("+stacktrace[i + 1].getFileName() + ":" + stacktrace[i + 1].getLineNumber()+")"; 
       return tag; 
      } 
     } 
     return tag; 
    } 

    public static void Log(String message){ 
     Log.v(getTag(), getCallerName() + " " + message); 
    } 
} 

utilizzati:

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.sample_main); 
      MyDebugLog.Log("XXXXX"); 
    } 

uscita:

V/(MainActivity.java:117): onCreate XXXXX 

Esempio di array:

01.235.
getTag Sample of stacktace array: 

    Method: [0]getThreadStackTrace 
    Method: [1]getStackTrace 
    Method: [2]getTag 
    Method: [3]Log     <== Method for external call 
    ... 
getName Sample of stacktace array: 
    Method: [0]getThreadStackTrace 
    Method: [1]getStackTrace 
    Method: [2]getCallerName 
    Method: [3]Log 
    Method: [4]onCreate   <== Our external method 
    Method: [5]performCreate 
    ... 
0

Ho ottimizzato il codice che viene discusso qui e personalizzato per ottenere il metodo di richiamo. Ciò che il codice fa è iterare sugli elementi di traccia stack e non appena trova il nome del metodo che viene invocato, ottiene il nome del metodo precedente, che a sua volta sarà il metodo che sta invocando questo metodo.

private String method() { 
    String methodName=null; 
    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); 
    for (int i = 0; i < stacktrace.length; i++) { 
     if(stacktrace[i].getMethodName().equals("method")) { 
      methodName = stacktrace[i+1].getMethodName(); 
      break; 
     } 
    } 
     return methodName; 

} 
Problemi correlati