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

Java или любой другой язык: какой метод/класс вызывал мой?

Я хотел бы написать внутренний код для моего метода, который выведет, какой метод/класс вызвал его.

(Мое предположение заключается в том, что я ничего не могу изменить, кроме моего метода.)

Как насчет других языков программирования?

EDIT: Спасибо, ребята, как насчет JavaScript? питон? С++?

4b9b3361

Ответ 1

Это относится к Java.

Вы можете использовать Thread.currentThread(). getStackTrace(). Это вернет массив StackTraceElements.

Второй элемент в массиве будет вызывающим методом.

Пример:

public void methodThatPrintsCaller() {
    StackTraceElement elem = Thread.currentThread.getStackTrace()[2];
    System.out.println(elem);

    // rest of you code
}

Ответ 2

Если все, что вы хотите сделать, это распечатать трассировку стека и пойти на охоту за классом, используйте

Thread.dumpStack();

См. API doc.

Ответ 3

У Джастина общий случай; Я хотел упомянуть два особых случая, продемонстрированных этим сниппитом:

import java.util.Comparator;

public class WhoCalledMe {

    public static void main(String[] args) {
        ((Comparator)(new SomeReifiedGeneric())).compare(null, null);
        new WhoCalledMe().new SomeInnerClass().someInnerMethod();
    }

    public static StackTraceElement getCaller() {
        //since it a library function we use 3 instead of 2 to ignore ourself
        return Thread.currentThread().getStackTrace()[3];
    }

    private void somePrivateMethod() {
        System.out.println("somePrivateMethod() called by: " + WhoCalledMe.getCaller());
    }

    private class SomeInnerClass {
        public void someInnerMethod() {
            somePrivateMethod();
        }
    }
}

class SomeReifiedGeneric implements Comparator<SomeReifiedGeneric> {
    public int compare(SomeReifiedGeneric o1, SomeReifiedGeneric o2) {
        System.out.println("SomeRefiedGeneric.compare() called by: " + WhoCalledMe.getCaller());
        return 0;
    }
}

Отпечатки:

SomeRefiedGeneric.compare() called by: SomeReifiedGeneric.compare(WhoCalledMe.java:1)
somePrivateMethod() called by: WhoCalledMe.access$0(WhoCalledMe.java:14)

Даже если первый называется "напрямую" из main(), а второй из SomeInnerClass.someInnerMethod(). Это два случая, когда между этими двумя методами существует прозрачный вызов.

  • В первом случае это связано с тем, что мы вызываем метод моста в общий метод, добавленный компилятором, чтобы гарантировать, что SomeReifiedGeneric может использоваться как необработанный тип.
  • Во втором случае это потому, что мы вызываем частный член WhoCalledMe из внутреннего класса. Для этого компилятор добавляет синтетический метод в качестве промежуточного для переопределения проблем видимости.

Ответ 5

Поскольку вы спрашивали о других языках, Tcl дает вам команду (информационный уровень), которая позволяет вам проверять стек вызовов. Например, [info level -1] возвращает вызывающего абонента текущей процедуры, а также аргументы, используемые для вызова текущей процедуры.

Ответ 6

В Python вы используете модуль inspect. Получение имени функции и имени файла легко, как вы видите в приведенном ниже примере.

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

import inspect

def find_caller():
    caller_frame = inspect.currentframe().f_back
    print "Called by function:", caller_frame.f_code.co_name
    print "In file           :", caller_frame.f_code.co_filename
    #Alternative, probably more portable way
    #print inspect.getframeinfo(caller_frame)

def foo():
    find_caller()

foo()

Ответ 8

В Python вы должны использовать traceback или проверять модули. Эти модули будут защищать вас от деталей реализации интерпретатора, которые могут отличаться даже сегодня (например, IronPython, Jython) и могут еще больше измениться в будущем. Таким образом, эти модули делают это под стандартным интерпретатором Python, однако, с sys._getframe(). В частности, sys._getframe (1).f_code.co_name предоставляет необходимую информацию.