2010-08-12 3 views
11

Ich möchte einen internen Code in meine Methode schreiben, die die Methode/Klasse drucken, die sie aufgerufen hat.Java oder eine andere Sprache: Welche Methode/Klasse hat meine aufgerufen?

(Meine Vermutung ist, dass ich nichts, aber meine Methode ändern können ..)

Was ist mit anderen Programmiersprachen?

EDIT: Danke Jungs, wie wäre es mit JavaScript? Python? C++?

+2

Ich bin immer wieder erstaunt, welche seltsamen Hacks manche Leute "gerne schreiben würden". Nichts für ungut. – delnan

+3

@del Das ist nicht wirklich ein Hack. Es ist im Grunde eine Form der Protokollierung, die wirklich hilfreich sein kann. – jjnguy

+1

ausspionieren .. :-) – DuduAlul

Antwort

18

Diese auf Java spezifisch ist.

Sie können Thread.currentThread().getStackTrace() verwenden. Dies wird ein Array von StackTraceElements zurückgeben.

Das zweite Element im Array wird die aufrufende Methode sein.

Beispiel:

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

    // rest of you code 
} 
+0

Es gibt ein paar spezielle Fälle, die für einen Kommentar nicht geeignet waren, ich habe sie in ihre eigene Antwort eingefügt. –

+0

Java-Arrays sind jetzt 1-basiert? ;) – Stroboskop

+1

@strob, nein. Du wirst 'arr [2]' oder die zweite Sache nennen. (Technisch ist es die 3. Sache) (Aber, was nennst du dann die 0. Sache?) – jjnguy

2

Die Reihenfolge der Methodenaufrufe befindet sich im Stapel. So bekommst du den Stack: Get current stack trace in Java dann bekommst du den vorherigen Artikel.

+1

Hehe, das bezieht sich auf meine Antwort! Vielen Dank. – jjnguy

4

Wenn alles, was Sie tun wollen Ausdruck der Stack-Trace ist und gehen für die Klasse der Jagd, verwenden

Thread.dumpStack(); 

die API doc See.

1

Da Sie über andere Sprachen gefragt, Tcl gibt Ihnen einen Befehl (info level), die Sie den Call-Stack untersuchen lässt. Beispielsweise gibt [info level -1] den Aufrufer der aktuellen Prozedur sowie die zum Aufruf der aktuellen Prozedur verwendeten Argumente zurück.

4

Justin hat den allgemeinen Fall unten; Ich wollte dieses snippit zeigen zwei Sonderfälle erwähnen:

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; 
    } 
} 

Diese Drucke:

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

Auch wenn die ersten genannt wird „direkt“ von main() und den zweiten von SomeInnerClass.someInnerMethod(). Dies sind zwei Fälle, in denen zwischen den beiden Methoden ein transparenter Aufruf erfolgt.

  • Im ersten Fall ist dies, weil wir die bridge method auf eine generische Methode aufrufen, die vom Compiler hinzugefügt SomeReifiedGeneric, um sicherzustellen, können als Ausgangstyp verwendet werden.
  • Im zweiten Fall ist es, weil wir ein privates Mitglied von WhoCalledMe von einer inneren Klasse aufrufen. Um dies zu erreichen, fügt der Compiler eine synthetische Methode als Vermittler hinzu, um die Sichtbarkeitsprobleme zu überschreiben.
+2

Das sind einige gute Punkte. – jjnguy

0

In Python sollten Sie die Module traceback oder inspect verwenden. Diese Module werden Sie von den Implementierungsdetails des Interpreters abschirmen, die sich auch heute noch unterscheiden können (z. B. IronPython, Jython) und sich in Zukunft möglicherweise noch ändern können.Die Art und Weise, wie diese Module es heute unter dem Standard-Python-Interpreter tun, ist jedoch mit sys._getframe(). Insbesondere liefert sys._getframe (1) .f_code.co_name die gewünschten Informationen.

1

In Python verwenden Sie das Modul inspect. Den Namen und den Dateinamen der Funktion können Sie einfach abrufen, wie Sie im folgenden Beispiel sehen.

Die Funktion selbst ist mehr Arbeit. Ich denke, dass Sie die __import__ Funktion verwenden konnten, um das Modul des Anrufers zu importieren. Allerdings müssen Sie den Dateinamen irgendwie in einen gültigen Modulnamen konvertieren.

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() 
Verwandte Themen