2010-10-31 24 views
17

Bir test vakasını düzeltmek için, işlevin belirli bir arayan işlevinden çağrılıp çağrılmadığını belirtmem gerekiyor. Tanımlanan arabirimleri kırdığı için bir boole parametresi ekleyemem. Bu konuda nasıl giderim?Java: Arayanın işlev adı nasıl alınır

Bu başarmak istediğim şeydir. Burada, bir arabirim uygulaması olduğundan, işlem() parametrelerini değiştiremiyorum.

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

} 
+9

Hemen her koşulda bunun gerçekten çok kötü bir fikir olduğunu vurgulamak isterim. Bunu uygulamadan önce gerçekten iyi bir nedeniniz olduğundan emin olun. Olası tüm alternatifleri düşünün. Örneğin: bir arayüz ekleyebilir misiniz? –

+0

Onsuz bir yol buldum. Öneri için çok teşekkürler. – devnull

+3

Bunun gerçekten kötü bir fikir olmasının bir nedeni, tek uygulanabilir uygulama yaklaşımının Pahalı olmasıdır. –

cevap

54

Sen deneyebilirsiniz

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: bence getStackTrace() daha hızlıdır. – thejh

+1

doğru şekilde uygulandıysa, ikisi de aynıdır: "thread.getStackTrace()" return (new Exception()). GetStackTrace(); "eğer" thread "geçerli olanıdır. –

0

İşte bunu çağırır işlevin işlev adı Log yazdığı bir fonksiyondur. LogIt adlı bir işlev bulana kadar yığın izlemesini çalıştırır, sonra bir sonraki adı görüntüler. Bu kirli bir hack, bu yüzden hata ayıklamak için kullanmadığınız sürece yapmayın.

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

robot kullanımı için bir diğer örnek:

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

Kullanım:

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

Çıkış: dizilerin

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

Örnek:

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

Burada tartışılan kodu değiştirdim ve çağrı yöntemini almak için özelleştirdim. Buradaki kod, yığın izleme öğeleri üzerinde yineleme yapmaktır ve çağrılan yöntemin adını bulduğu anda, önceki yöntemin adını alır ve bu da bu yöntemi çağırmaktır.

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; 

}