Java: Как получить имя функции вызывающей стороны - PullRequest
20 голосов
/ 01 ноября 2010

Чтобы исправить контрольный пример, мне нужно определить, вызывается ли функция из определенной функции вызывающей стороны. Я не могу позволить себе добавить логический параметр, потому что он нарушит определенные интерфейсы. Как это сделать?

Это то, чего я хочу достичь. Здесь я не могу изменить параметры операции (), так как это реализация интерфейса.

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

}

Ответы [ 6 ]

58 голосов
/ 01 ноября 2010

Вы можете попробовать

StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
String methodName = e.getMethodName();
1 голос
/ 14 мая 2014

Вот функция, которую я написал, чтобы записать имя функции вызывающей ее функции. Он запускает трассировку стека, пока не найдет функцию с именем 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");
}
1 голос
/ 01 ноября 2010
0 голосов
/ 22 января 2019

Я иногда хочу сделать несколько выводов в 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
0 голосов
/ 05 октября 2017

Я изменил код, который здесь обсуждается, и настроил его для получения метода вызова. Здесь код выполняет итерацию по элементам трассировки стека, и как только он находит имя вызываемого метода, он получает имя предыдущего метода, который, в свою очередь, будет методом, вызывающим этот метод.

    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;

}
0 голосов
/ 29 марта 2017

Еще один пример использования 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);
    }
}

Использование:

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

Выход:

    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
    ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...