Java или любой другой язык: какой метод/класс вызывал мой?
Я хотел бы написать внутренний код для моего метода, который выведет, какой метод/класс вызвал его.
(Мое предположение заключается в том, что я ничего не могу изменить, кроме моего метода.)
Как насчет других языков программирования?
EDIT: Спасибо, ребята, как насчет JavaScript? питон? С++?
Ответы
Ответ 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 из внутреннего класса. Для этого компилятор добавляет синтетический метод в качестве промежуточного для переопределения проблем видимости.
Ответ 4
последовательность вызовов методов находится в стеке. вот как вы получаете стек: Получить текущую трассировку стека в Java, затем получить предыдущий элемент.
Ответ 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()
Ответ 7
Да, это возможно.
Посмотрите Thread.getStackTrace()
Ответ 8
В Python вы должны использовать traceback или проверять модули. Эти модули будут защищать вас от деталей реализации интерпретатора, которые могут отличаться даже сегодня (например, IronPython, Jython) и могут еще больше измениться в будущем. Таким образом, эти модули делают это под стандартным интерпретатором Python, однако, с sys._getframe(). В частности, sys._getframe (1).f_code.co_name предоставляет необходимую информацию.