Подтвердить что ты не робот

Java: как получить имя функции вызывающего абонента

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

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

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

}
4b9b3361

Ответ 1

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

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

Ответ 3

Здесь функция, которую я написал для входа в функцию имени функции вызывающей ее функции. Он запускает трассировку стека, пока не найдет функцию с именем 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");
}

Ответ 4

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

Ответ 5

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

    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;

}

Ответ 6

Иногда я хочу сделать некоторые выводы для 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

Ответ 7

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

    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