2010-10-31 19 views
17

Para arreglar un caso de prueba, necesito identificar si la función se llama desde una función de llamada particular. No puedo permitirme agregar un parámetro booleano porque rompería las interfaces definidas. ¿Como va esto?Java: cómo obtener el nombre de la función de llamada

Esto es lo que quiero lograr. Aquí no puedo cambiar los parámetros de operación() ya que es una implementación de interfaz.

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

} 
+9

Simplemente enfatizaría que en casi todas las circunstancias esta es una muy mala idea. Asegúrese de tener una muy buena razón antes de implementar esto. Considere todas las alternativas posibles. Por ejemplo: ¿puedes agregar una interfaz? –

+0

Encontré una manera sin eso. Muchas gracias por la sugerencia. – devnull

+3

Una de las razones por las cuales esta es una idea realmente mala es que el único enfoque de implementación viable es Caro. –

Respuesta

54

Usted podría intentar

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

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

+1

@mootinator: Creo que getStackTrace() es más rápido. – thejh

+1

si están implementados correctamente, ambos son iguales: 'thread.getStackTrace()' does 'return (new Exception()). GetStackTrace();' si el 'thread' es el actual. –

0

Aquí hay una función que escribí para registrar el nombre de la función de la función que llama. Se ejecuta en el seguimiento de la pila hasta que encuentra una función llamada logIt, luego muestra el siguiente nombre. Es un truco sucio, así que no lo hagas a menos que lo estés usando para depurar.

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

Otra muestra para el uso androide:

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

Utilización:

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

de salida:

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

de muestra de arrays:

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

Modifiqué el código que se está discutiendo aquí y lo personalicé para obtener el método de invocación. Lo que el código hace aquí es iterar sobre los elementos traza de la pila y, tan pronto como encuentra el nombre del método que se invoca, obtiene el nombre del método anterior, que a su vez será el método que invoca este método.

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; 

} 
Cuestiones relacionadas