Ottenere il nome del metodo attualmente in esecuzione


Risposte:


177

Thread.currentThread().getStackTrace()di solito conterrà il metodo da cui lo chiami ma ci sono insidie ​​(vedi Javadoc ):

Alcune macchine virtuali possono, in alcune circostanze, omettere uno o più frame di stack dalla traccia dello stack. In casi estremi, una macchina virtuale che non ha informazioni di traccia stack relative a questo thread è autorizzata a restituire un array di lunghezza zero da questo metodo.


7
La stessa trappola è vera per le tracce dello stack in eccezioni?
Nate Parsons,

8
Sì. La documentazione per Throwable . [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/… contiene esattamente lo stesso paragrafo.
Bombe,

4
La cosa fondamentale è che non è necessario che JVM sia in grado di fornire uno stack stack, ma che è stato fatto molto lavoro per rendere HotSpot molto affidabile. Devi sapere, tuttavia, nel caso in cui desideri che il tuo codice non si basi sul comportamento di una JVM specifica.
Thorbjørn Ravn Andersen,

La versione di Alexsmail di seguito non crea una traccia dello stack e ti dà accesso all'oggetto metodo reale, non solo al nome (quindi puoi scoprire anche il tipo di ritorno). Non ho segnato il banco ma sospetto che anche il suo metodo sia molto più veloce poiché le tracce dello stack tendono ad essere costose.
Gus,

La risposta di Devin sembra dare una risposta molto più concisa a questa domanda.
risingTide

310

Tecnicamente questo funzionerà ...

String name = new Object(){}.getClass().getEnclosingMethod().getName();

Tuttavia, durante la compilazione (ad es YourClass$1.class.) Verrà creata una nuova classe interna anonima . Quindi questo creerà un .classfile per ogni metodo che distribuisce questo trucco. Inoltre, viene creata un'istanza di oggetto altrimenti inutilizzata su ogni invocazione durante il runtime. Quindi questo può essere un trucco di debug accettabile, ma comporta un notevole sovraccarico.

Un vantaggio di questo trucco è che getEncosingMethod()restituisce java.lang.reflect.Methodche può essere utilizzato per recuperare tutte le altre informazioni del metodo, comprese annotazioni e nomi dei parametri. Ciò consente di distinguere tra metodi specifici con lo stesso nome (metodo overload).

Si noti che, secondo JavaDoc, getEnclosingMethod()questo trucco non dovrebbe essere lanciato SecurityExceptionpoiché le classi interne dovrebbero essere caricate usando lo stesso caricatore di classi. Quindi non è necessario controllare le condizioni di accesso anche se è presente un gestore della sicurezza.

È necessario utilizzare getEnclosingConstructor()per i costruttori. Durante i blocchi al di fuori dei metodi (nominati), getEnclosingMethod()restituisce null.


9
Questo non ti darà il metodo attualmente in esecuzione. Questo ti darà quel metodo in cui è definita una classe anonima / locale. - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000

7
class Local {}; String name = Local.class.getEnclosingMethod (). GetName ();
alexsmail,

21
@ shrini1000 l'idea è quella di utilizzare questo frammento dove sono necessarie le informazioni e non inserirle in una routine di libreria.
Thorbjørn Ravn Andersen,

4
Grazie per i suggerimenti! Invece di creare un nuovo oggetto, basta usare this.getClass (). GetEnclosingMethod (). GetName ();
Lilo,

3
@Lilo errato. getEnclosingMethodottiene il nome del metodo in cui è definita la classe. this.getClass()non ti aiuterà affatto. @wutzebaer perché dovresti averne bisogno? Hai già accesso a loro.
Hazel Troost,

134

Gennaio 2009:
sarebbe un codice completo (da usare tenendo presente l'avvertenza di @ Bombe ):

/**
 * Get the method name for a depth in call stack. <br />
 * Utility function
 * @param depth depth in the call stack (0 means current method, 1 means call method, ...)
 * @return method name
 */
public static String getMethodName(final int depth)
{
  final StackTraceElement[] ste = Thread.currentThread().getStackTrace();

  //System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
  // return ste[ste.length - depth].getMethodName();  //Wrong, fails for depth = 0
  return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky
}

Altro in questa domanda .

Aggiornamento dicembre 2011:

commenti bluastri :

Uso JRE 6 e mi dà un nome metodo errato.
Funziona se scrivoste[2 + depth].getMethodName().

  • 0è getStackTrace(),
  • 1è getMethodName(int depth)e
  • 2 sta invocando il metodo.

virgo47 's risposta (upvoted) in realtà calcola l'indice di diritto di applicare al fine di recuperare il nome del metodo.


2
Dice solo "principale" per me. : - /
contratto del Prof. Falken è stato violato

@Amigable: hai provato a stampare tutto l' StackTraceElementarray a scopo di debug e vedere se 'main' è effettivamente il metodo giusto?
VonC,

7
Uso JRE 6 e mi dà un nome metodo errato. Funziona se scrivo ste[2 + depth].getMethodName(). 0 è getStackTrace(), 1 è getMethodName(int depth)e 2 sta invocando il metodo. Vedi anche la risposta di @ virgo47 .
bluastro

2
@lulu: buon punto. Ho incluso il tuo commento e un riferimento alla risposta di virgo47 nella mia.
VonC,

@VonC Questa implementazione è davvero corretta? la profondità qui deve essere ste.length + 1 per questo per fornire il metodo corrente. Non dovrebbe essere ste [profondità + 1] se vogliamo consentire la profondità = 0?
mmm

85

Abbiamo usato questo codice per mitigare la potenziale variabilità nell'indice di traccia dello stack - ora basta chiamare methodName util:

public class MethodNameTest {
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            i++;
            if (ste.getClassName().equals(MethodNameTest.class.getName())) {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static void main(String[] args) {
        System.out.println("methodName() = " + methodName());
        System.out.println("CLIENT_CODE_STACK_INDEX = " + CLIENT_CODE_STACK_INDEX);
    }

    public static String methodName() {
        return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
    }
}

Sembra troppo ingegnerizzato, ma avevamo un numero fisso per JDK 1.5 e siamo rimasti un po 'sorpresi che sia cambiato quando siamo passati a JDK 1.6. Ora è lo stesso in Java 6/7, ma non lo sai mai. Non è una prova delle modifiche apportate a quell'indice durante il runtime, ma si spera che HotSpot non faccia così male. :-)


1
Questo è ancora sottilmente dipendente dal fornitore. JVM non è tenuto a fornire dati affidabili per questo codice.
Thorbjørn Ravn Andersen,

6
Secondo le specifiche JVM, la JVM non è tenuta a fornire tracce dello stack completo (ottimizzazione, inline e tutto il resto) e hai già scoperto che la tua euristica è cambiata tra Oracle Java 5 e Oracle Java 6. Non c'è nulla che garantisca che qualsiasi altra JVM lo farà comportarsi come previsto nel proprio codice, quindi si sta sottilmente affidandosi a comportamenti specifici del fornitore. Il che è perfettamente corretto, a condizione che tu ne sia consapevole, ma se, ad esempio, devi distribuire su una JVM IBM (che dobbiamo) o su un'istanza Zing, potresti dover rivedere la tua euristica.
Thorbjørn Ravn Andersen,

1
Questa sembra la più solida di tutte le opzioni qui presentate, nonostante le dipendenze.
Ian

46
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

il nome avrà valore foo.


5
Local.class.getEnclosingMethod () era null. jdk1.6.0_31, gioca 1.2.5
eigil

@eigil è interessante ma senza ulteriori informazioni è difficile dire cosa è andato "storto" o quando dovremmo aspettarcinull
Maarten Bodewes,

Questo è lo stesso trucco di questa risposta . Ha il vantaggio di non creare un'istanza di oggetto spurio, ha lo svantaggio di richiedere una dichiarazione di classe che non può essere inserita nell'istruzione (cioè normalmente richiede una riga di codice aggiuntiva).
Maarten Bodewes,

@eigil hai definito la classe all'interno di una classe (esempio SomeClass) o all'interno di un metodo (esempio pippo)? Ho scoperto che la definizione di una sottoclasse senza essere racchiusa in un metodo - o in un costruttore - farà sì che getEnclosingMethod () restituisca null.
DN

Abbastanza sicuro di aver fatto esattamente come descritto in questa risposta. Penso che sia qualcosa di strano con la trama. Testato in Java "normale" senza alcun problema.
eigil,

36

Entrambe queste opzioni funzionano per me con Java:

new Object(){}.getClass().getEnclosingMethod().getName()

O:

Thread.currentThread().getStackTrace()[1].getMethodName()

1
per i metodi statici usare: <Class> .class.getEnclosingMethod (). getName ()
jellobird

fare attenzione alla matrice vuota in base alla risposta di Bombe e all'indicazione javadoc. Alcuni JVM potrebbero non riempire l'array stacktrace?
el-teedee,

34

Il modo più veloce che ho trovato è che:

import java.lang.reflect.Method;

public class TraceHelper {
    // save it static to have it available on every call
    private static Method m;

    static {
        try {
            m = Throwable.class.getDeclaredMethod("getStackTraceElement",
                    int.class);
            m.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getMethodName(final int depth) {
        try {
            StackTraceElement element = (StackTraceElement) m.invoke(
                    new Throwable(), depth + 1);
            return element.getMethodName();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

Accede direttamente al metodo nativo getStackTraceElement (int depth). E memorizza il metodo accessibile in una variabile statica.


3
Il più veloce in termini di prestazioni? Qualche micro-benchmark per supportare l'affermazione?
Ibrahim Arief,

10
+1. Usando un semplice ciclo temporizzato su 1.6, 1.000.000 di iterazioni usando questo metodo hanno richiesto 1219ms, mentre l'utilizzo new Throwable().getStackTrace()ha richiesto 5614ms.
ach

1
m.setAccessible (true); dovrebbe essere circondato da AccessController.doPrivileged. Qualcosa da considerare, non una regola difficile direi
avanderw,

6
Testato nel 2016 e questo continua ad essere il più veloce. Come @ach ho usato iterazioni 1M. 1.7_79: 1.6s contro 15.2s 1.8_74: 1.8s contro 16.0s. FWIW la lunghezza del mio benchmark ste array == 23 ma questo metodo rimane veloce indipendentemente dalla profondità dello stack.
Ryan,

25

Usa il seguente codice:

    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
    String methodName = e.getMethodName();
    System.out.println(methodName);

2
Questo stampa "getStackTrace" per me - Sto usando Java 1.5
Zack Macomber

fare attenzione alla matrice vuota in base alla risposta di Bombe e all'indicazione javadoc. Alcuni JVM potrebbero non riempire l'array stacktrace?
el-teedee,

16
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }

Sì, di gran lunga il migliore ... trasformalo in un metodo e ottieni il terzo ([2]) frame (o come si chiama) nella traccia.
mike rodent,

14

Questa è un'espansione della risposta di virgo47 (sopra).

Fornisce alcuni metodi statici per ottenere i nomi di classe / metodo correnti e invocanti.

/* Utility class: Getting the name of the current executing method 
 * /programming/442747/getting-the-name-of-the-current-executing-method
 * 
 * Provides: 
 * 
 *      getCurrentClassName()
 *      getCurrentMethodName()
 *      getCurrentFileName()
 * 
 *      getInvokingClassName()
 *      getInvokingMethodName()
 *      getInvokingFileName()
 *
 * Nb. Using StackTrace's to get this info is expensive. There are more optimised ways to obtain
 * method names. See other stackoverflow posts eg. /programming/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection/2924426#2924426
 *
 * 29/09/2012 (lem) - added methods to return (1) fully qualified names and (2) invoking class/method names
 */
package com.stackoverflow.util;

public class StackTraceInfo
{
    /* (Lifted from virgo47's stackoverflow answer) */
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste: Thread.currentThread().getStackTrace())
        {
            i++;
            if (ste.getClassName().equals(StackTraceInfo.class.getName()))
            {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static String getCurrentMethodName()
    {
        return getCurrentMethodName(1);     // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentMethodName(int offset)
    {
        return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getMethodName();
    }

    public static String getCurrentClassName()
    {
        return getCurrentClassName(1);      // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentClassName(int offset)
    {
    return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getClassName();
    }

    public static String getCurrentFileName()
    {
        return getCurrentFileName(1);     // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentFileName(int offset)
    {
        String filename = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getFileName();
        int lineNumber = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getLineNumber();

        return filename + ":" + lineNumber;
    }

    public static String getInvokingMethodName()
    {
        return getInvokingMethodName(2); 
    }

    private static String getInvokingMethodName(int offset)
    {
        return getCurrentMethodName(offset + 1);    // re-uses getCurrentMethodName() with desired index
    }

    public static String getInvokingClassName()
    {
        return getInvokingClassName(2); 
    }

    private static String getInvokingClassName(int offset)
    {
        return getCurrentClassName(offset + 1);     // re-uses getCurrentClassName() with desired index
    }

    public static String getInvokingFileName()
    {
        return getInvokingFileName(2); 
    }

    private static String getInvokingFileName(int offset)
    {
        return getCurrentFileName(offset + 1);     // re-uses getCurrentFileName() with desired index
    }

    public static String getCurrentMethodNameFqn()
    {
        return getCurrentMethodNameFqn(1);
    }

    private static String getCurrentMethodNameFqn(int offset)
    {
        String currentClassName = getCurrentClassName(offset + 1);
        String currentMethodName = getCurrentMethodName(offset + 1);

        return currentClassName + "." + currentMethodName ;
    }

    public static String getCurrentFileNameFqn()
    {
        String CurrentMethodNameFqn = getCurrentMethodNameFqn(1);
        String currentFileName = getCurrentFileName(1);

        return CurrentMethodNameFqn + "(" + currentFileName + ")";
    }

    public static String getInvokingMethodNameFqn()
    {
        return getInvokingMethodNameFqn(2);
    }

    private static String getInvokingMethodNameFqn(int offset)
    {
        String invokingClassName = getInvokingClassName(offset + 1);
        String invokingMethodName = getInvokingMethodName(offset + 1);

        return invokingClassName + "." + invokingMethodName;
    }

    public static String getInvokingFileNameFqn()
    {
        String invokingMethodNameFqn = getInvokingMethodNameFqn(2);
        String invokingFileName = getInvokingFileName(2);

        return invokingMethodNameFqn + "(" + invokingFileName + ")";
    }
}

3
Questo in combinazione con la risposta di @mklemenz è un modo molto veloce e pulito per accedere alle informazioni dello stack.
Octavia Togami,

12

Per ottenere il nome del metodo che ha chiamato il metodo corrente è possibile utilizzare:

new Exception("is not thrown").getStackTrace()[1].getMethodName()

Funziona sul mio MacBook e sul mio telefono Android

Ho anche provato:

Thread.currentThread().getStackTrace()[1]

ma Android restituirà "getStackTrace" che potrei risolvere con Android

Thread.currentThread().getStackTrace()[2]

ma poi ricevo la risposta sbagliata sul mio MacBook


Nei recenti test su Android, ha funzionato meglio per me getStackTrace()[0]piuttosto che getStackTrace()[1]. YMMV.
mbm29414

per Android èThread.currentThread().getStackTrace()[2]
Ninja il

11

Util.java:

public static String getCurrentClassAndMethodNames() {
    final StackTraceElement e = Thread.currentThread().getStackTrace()[2];
    final String s = e.getClassName();
    return s.substring(s.lastIndexOf('.') + 1, s.length()) + "." + e.getMethodName();
}

SomeClass.java:

public class SomeClass {
    public static void main(String[] args) {
        System.out.println(Util.getCurrentClassAndMethodNames()); // output: SomeClass.main
    }
}

final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; lavori; e.getClassName();restituisce il nome completo della classe e e.getMethodName()restituisce il nome del methon.
Segna il

1
getStackTrace()[2]è sbagliato, deve essere getStackTrace()[3]perché: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] La funzione a () che chiama questo
PhilLab

11

Questo può essere fatto usando StackWalkerda Java 9.

public static String getCurrentMethodName() {
    return StackWalker.getInstance()
                      .walk(s -> s.skip(1).findFirst())
                      .get()
                      .getMethodName();
}

public static String getCallerMethodName() {
    return StackWalker.getInstance()
                      .walk(s -> s.skip(2).findFirst())
                      .get()
                      .getMethodName();
}

StackWalkerè progettato per essere pigro, quindi è probabile che sia più efficiente di, diciamo, Thread.getStackTraceche crea avidamente un array per l'intero callstack. Vedere anche il JEP per ulteriori informazioni.


5

Un metodo alternativo è quello di creare, ma non generare, un'eccezione e utilizzare quell'oggetto da cui ottenere i dati di traccia dello stack, poiché il metodo che la racchiude sarà in genere all'indice 0, purché la JVM memorizzi tali informazioni, come altri hanno sopra menzionato. Questo non è il metodo più economico, tuttavia.

Da Throwable.getStackTrace () (questo è stato lo stesso almeno da Java 5):

L'elemento zeroth dell'array (supponendo che la lunghezza dell'array sia diverso da zero) rappresenta la parte superiore dello stack, che è l'ultima chiamata del metodo nella sequenza. In genere , questo è il punto in cui questo lancio è stato creato e lanciato.

Lo snippet di seguito presuppone che la classe sia non statica (a causa di getClass ()), ma questo è un lato.

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());

4
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);

1
Vedi le risposte di mvanle virgo47 sopra e il commento di thorbjorn-ravn-andersen. Ripetizione, codice non accurato e non affidabile.
alexsmail,

@ShivaKomuravelly Sì, ma in nessuna situazione sembra, quindi -1 anche da me.
Maarten Bodewes,

3

Ho una soluzione usando questo (in Android)

/**
 * @param className       fully qualified className
 *                        <br/>
 *                        <code>YourClassName.class.getName();</code>
 *                        <br/><br/>
 * @param classSimpleName simpleClassName
 *                        <br/>
 *                        <code>YourClassName.class.getSimpleName();</code>
 *                        <br/><br/>
 */
public static void getStackTrace(final String className, final String classSimpleName) {
    final StackTraceElement[] steArray = Thread.currentThread().getStackTrace();
    int index = 0;
    for (StackTraceElement ste : steArray) {
        if (ste.getClassName().equals(className)) {
            break;
        }
        index++;
    }
    if (index >= steArray.length) {
        // Little Hacky
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[3].getMethodName(), String.valueOf(steArray[3].getLineNumber())}));
    } else {
        // Legitimate
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[index].getMethodName(), String.valueOf(steArray[index].getLineNumber())}));
    }
}



1

La maggior parte delle risposte qui sembra sbagliata.

    public static String getCurrentMethod() {
            return getCurrentMethod(1);
    }
    public static String getCurrentMethod(int skip) {
            return Thread.currentThread().getStackTrace()[1 + 1 + skip].getMethodName();
    }

Esempio:

    public static void main(String[] args) {
            aaa();
    }

    public static void aaa() {
            System.out.println("aaa  -> "  + getCurrentMethod( ) );
            System.out.println("aaa  -> "  + getCurrentMethod(0) );
            System.out.println("main -> "  + getCurrentMethod(1) );
    }

Uscite:

aaa  -> aaa
aaa  -> aaa
main -> main

Grazie per la tua utile risposta.
Amerllic,

Potresti chiarire perché la maggior parte delle risposte sembra sbagliata per te? Ci sono molte risposte e non sono molto esperto in Java per leggerle tutte e capire qual è la differenza tra loro e la tua risposta. :(
Xobotun,

@mmm Siamo spiacenti, ma non sono d'accordo. Vengo qui per imparare e così faccio molti altri, credo. Non riesco proprio a capire perché pensi che non meriti di saperne di più su questo argomento. Voglio fare meno errori nel mio codice e avvertire gli altri, di non seguire un culto del carico. Avresti potuto almeno chiarire su quale versione Java questo codice dovrebbe essere corretto. :( Una risposta di seguito dice che c'è stato un cambiamento nello stacktrace tra 1.5 e 1.6. Forse insinui che c'è qualcosa di simile nel prossimo Java 14, come posso sapere. O un altro fornitore potrebbe avere. Scusa se ho frainteso la tua risposta come maleducata uno
Xobotun,

0

Ho riscritto un po ' la risposta del maklemenz :

private static Method m;

static {
    try {
        m = Throwable.class.getDeclaredMethod(
            "getStackTraceElement",
            int.class
        );
    }
    catch (final NoSuchMethodException e) {
        throw new NoSuchMethodUncheckedException(e);
    }
    catch (final SecurityException e) {
        throw new SecurityUncheckedException(e);
    }
}


public static String getMethodName(int depth) {
    StackTraceElement element;

    final boolean accessible = m.isAccessible();
    m.setAccessible(true);

    try {
        element = (StackTraceElement) m.invoke(new Throwable(), 1 + depth);
    }
    catch (final IllegalAccessException e) {
        throw new IllegalAccessUncheckedException(e);
    }
    catch (final InvocationTargetException e) {
        throw new InvocationTargetUncheckedException(e);
    }
    finally {
        m.setAccessible(accessible);
    }

    return element.getMethodName();
}

public static String getMethodName() {
    return getMethodName(1);
}

-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();

11
Modifica con ulteriori informazioni. Le risposte di solo codice e "prova questo" sono scoraggiate, perché non contengono contenuti ricercabili e non spiegano perché qualcuno dovrebbe "provare questo".
Abarisone,

1
Sebbene questo codice possa aiutare a risolvere il problema, non spiega perché e / o come risponde alla domanda. Fornire questo contesto aggiuntivo migliorerebbe significativamente il suo valore educativo a lungo termine. Si prega di modificare la risposta di aggiungere spiegazioni, tra cui quello che si applicano le limitazioni e le assunzioni.
Toby Speight,

1
Solo per Java 7+, ma modo conciso per ottenere il nome del metodo. Tuttavia, rimangono le considerazioni sulle prestazioni di tale chiamata.
Benj,

6
getEnclosingMethod()lancia una NullPointerExceptionper me in Java 7.
Markus L

2
Java.lang.Class.getEnclosingMethod () restituisce un oggetto Method che rappresenta il metodo che racchiude immediatamente la classe sottostante, se questo oggetto Class rappresenta una classe locale o anonima all'interno di un metodo, altrimenti restituisce null.
Stufa

-5

Cosa c'è di sbagliato in questo approccio:

class Example {
    FileOutputStream fileOutputStream;

    public Example() {
        //System.out.println("Example.Example()");

        debug("Example.Example()",false); // toggle

        try {
            fileOutputStream = new FileOutputStream("debug.txt");
        } catch (Exception exception) {
             debug(exception + Calendar.getInstance().getTime());
        }
    }

    private boolean was911AnInsideJob() {
        System.out.println("Example.was911AnInsideJob()");
        return true;
    }

    public boolean shouldGWBushBeImpeached(){
        System.out.println("Example.shouldGWBushBeImpeached()");
        return true;
    }

    public void setPunishment(int yearsInJail){
        debug("Server.setPunishment(int yearsInJail=" + yearsInJail + ")",true);
    }
}

E prima che le persone impazziscano nell'usare System.out.println(...)te, potresti sempre e dovresti creare un metodo in modo che l'output possa essere reindirizzato, ad esempio:

    private void debug (Object object) {
        debug(object,true);
    }

    private void dedub(Object object, boolean debug) {
        if (debug) {
            System.out.println(object);

            // you can also write to a file but make sure the output stream
            // ISN'T opened every time debug(Object object) is called

            fileOutputStream.write(object.toString().getBytes());
        }
    }

4
@ Saksham mi sembra che in realtà sia stato un tentativo di rispondere alla domanda. Non un grande tentativo, ma comunque un tentativo.
Ivarni,

@ivarni "non è un buon tentativo"? che cosa c'è che non va? conosci il "principio del bacio"?
johnny,

@ Saksham era retorico.
johnny,

5
@johnny Nel codebase che ho davanti a me in questo momento ci sono 271 classi. Anche con una (bassa stima) di 5 metodi per classe che supera i 1300 metodi. E questo non è nemmeno un grande codebase. Non vedi il problema con il ridimensionamento del tuo approccio? Sono abbastanza felice di accettare di non essere d'accordo, ma è per questo che ho detto che non è un buon tentativo. Introduce un'enorme quantità di sovraccarico in qualsiasi base di codice non banale.
Ivarni,

1
@johnny Immagino di aver visto troppi casi in cui il nome del metodo non corrisponde alla stringa che mi ha inviato nella direzione sbagliata durante il debug. Ma in Java penso ancora che il tuo suggerimento sia il migliore, le altre alternative "costano" troppo.
Solo un altro metaprogramma il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.