Java:如何获取调用方函数名

Java:如何获取调用方函数名,java,unit-testing,Java,Unit Testing,为了修复测试用例,我需要确定该函数是否是从特定的调用方函数调用的。我负担不起添加布尔参数,因为它会破坏定义的接口。怎么办 这就是我想要实现的目标。这里我不能更改operation()的参数,因为它是一个接口实现 operation() { if not called from performancetest() method do expensive bookkeeping operation ... } 你可以试试 StackTraceElement

为了修复测试用例,我需要确定该函数是否是从特定的调用方函数调用的。我负担不起添加布尔参数,因为它会破坏定义的接口。怎么办

这就是我想要实现的目标。这里我不能更改operation()的参数,因为它是一个接口实现

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

}
你可以试试

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

我写了一个函数来记录调用它的函数的函数名。它运行堆栈跟踪,直到找到名为logIt的函数,然后显示下一个名称。这是一个肮脏的黑客,所以不要这样做,除非你用它来调试

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");
}
private static void logIt(){
StackTraceElement[]stacktrace=Thread.currentThread().getStackTrace();
布尔值=假;
布尔foundMe=false;

对于(int i=0;i另一个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);
    }
}
输出:

    V/(MainActivity.java:117): onCreate XXXXX
阵列示例:

 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
    ...
stacktace数组的getTag示例:
方法:[0]getThreadStackTrace
方法:[1]getStackTrace
方法:[2]getTag

方法:[3]Log我调整了这里讨论的代码,并对其进行了定制,以获得调用方法。这里的代码所做的是迭代堆栈跟踪元素,一旦找到被调用的方法的名称,它就会获得前一个方法的名称,而前一个方法将是调用此方法的方法

    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;

}
私有字符串方法(){
字符串methodName=null;
StackTraceElement[]stacktrace=Thread.currentThread().getStackTrace();
对于(int i=0;i
有时我想对logcat进行一些输出。因此我编写了一个带有一些测试方法的小类:

public class Common {

    // can be used as test-flag anywhere in the app (set to false, when release the app)
    public static boolean b_TEST_MODE = true;

    public static void echo(String message) {
        if (b_TEST_MODE) {
            StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
            // subtring(25) is to cut off app-name from output
            System.out.println(">>> " + stackTraceElements[3].toString().substring(25) + ": " + message);
        }
    }
}
现在,您可以在应用程序中的任何位置调用它以获取一些信息:

String sSQLQuery = "SELECT * FROM database WHERE id=23";
Common.echo(sSQLQuery);
logcat打印出:

>>> MainActivity.onCreate(MainActivity.java:46): SELECT * FROM dateabase WHERE id=23

我不知道为什么,但在我的车间里,开发系统不同于测试和生产环境在堆栈中的位置变化。我被迫在堆栈中循环,以从堆栈跟踪的下一个元素中找到并获取调用方法。虽然有点笨拙,但到目前为止一直在返回所需的方法。我使用这个作为我的错误处理的一部分,我将识别在何处捕获异常

    List<String> list = new ArrayList<String>();
    StackTraceElement[] elements = Thread.currentThread().getStackTrace();
    for (int i = 0; i < Thread.currentThread().getStackTrace().length; i++) {
        System.out.println("Stack: "
                + i
                + " Class: "
                + elements[i].getClassName()
                + " Method: "
                + elements[i].getMethodName());
        if (elements[i].getMethodName().equals("<init>")) {
            list.add(elements[i + 1].getClassName());
            list.add(elements[i + 1].getMethodName());
             break;
        } // if
    } // for
List List=new ArrayList();
StackTraceElement[]元素=Thread.currentThread().getStackTrace();
对于(int i=0;i我只是强调,在几乎所有的情况下,这是一个非常糟糕的想法。在实施之前,一定要有一个非常好的理由。考虑任何和所有可能的选择。例如:你能添加一个接口吗?我发现没有它的一种方法。非常感谢这个建议。一个原因,这是一个非常糟糕的想法。唯一可行的实现方法是昂贵的。仅仅为了修复一个测试用例,这是一个特别糟糕的想法。new Throwable().fillInStackTrace().getStackTrace()[1]。getMethodName()@mootinator:我认为getStackTrace()更快。如果正确实现,它们是相同的:
thread.getStackTrace()
是否返回(新异常()).getStackTrace();
如果
线程
是当前线程。@mootinator-调用
fillInStackTrace()
是多余的。如何获得完全限定的方法名?像这样,我目前正在使用它调试一些RXJava东西,以确定谁在调用一个方法两次!谢谢!
    List<String> list = new ArrayList<String>();
    StackTraceElement[] elements = Thread.currentThread().getStackTrace();
    for (int i = 0; i < Thread.currentThread().getStackTrace().length; i++) {
        System.out.println("Stack: "
                + i
                + " Class: "
                + elements[i].getClassName()
                + " Method: "
                + elements[i].getMethodName());
        if (elements[i].getMethodName().equals("<init>")) {
            list.add(elements[i + 1].getClassName());
            list.add(elements[i + 1].getMethodName());
             break;
        } // if
    } // for