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

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

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

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

РЕДАКТИРОВАТЬ: Спасибо, ребята, как насчет JavaScript?питон?C ++?

Ответы [ 8 ]

19 голосов
/ 12 августа 2010

Это специфично для Java.

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

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

Пример:

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

    // rest of you code
}
4 голосов
/ 12 августа 2010

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

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's 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 голосов
/ 12 августа 2010

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

Thread.dumpStack();

См. API документ .

3 голосов
/ 12 августа 2010

последовательность вызовов методов находится в стеке. вот как вы получаете стек: Получите текущую трассировку стека в Java , затем получите предыдущий элемент.

1 голос
/ 12 августа 2010

В 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()
1 голос
/ 12 августа 2010

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

0 голосов
/ 12 августа 2010

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

0 голосов
/ 12 августа 2010

Да, это возможно.

Посмотрите на Thread.getStackTrace ()

...