2010-08-12 5 views
11

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

(Мое предположение, что я ничего не могу, но мой метод изменить ..)

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

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

+2

Я неоднократно поражаюсь тому, что странные хаки, некоторые люди «хотели бы написать». Не было никакого преступления. – delnan

+3

@del Это на самом деле не хак. Это в основном форма ведения журнала, которая может быть очень полезной. – jjnguy

+1

geeking out .. :-) – DuduAlul

ответ

18

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

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

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

Пример:

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

    // rest of you code 
} 
+0

Есть несколько особых случаев, которые не подходят для комментариев, я ставлю их в свой ответ. –

+0

Итак, Java-массивы теперь основаны на 1? ;) – Stroboskop

+1

@strob, no. Вы будете называть 'arr [2]' или 2-е. (Технически это 3-е место) (Но, что вы называете 0-й?) – jjnguy

2

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

+1

Хе-хе, это ссылки на мой ответ! Благодарю. – jjnguy

4

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

Thread.dumpStack(); 

См API doc.

1

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

4

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

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(). Это два случая, когда между этими двумя методами существует прозрачный вызов.

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

Это хорошие моменты. – jjnguy

0

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

1

В 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() 
Смежные вопросы