Obtenir le nom de la méthode en cours d'exécution

470

Existe-t-il un moyen d'obtenir le nom de la méthode en cours d'exécution en Java?

Omar Kooheji
la source

Réponses:

177

Thread.currentThread().getStackTrace()contiendra généralement la méthode à partir de laquelle vous l'appelez, mais il y a des pièges (voir Javadoc ):

Certaines machines virtuelles peuvent, dans certaines circonstances, omettre une ou plusieurs trames de pile de la trace de pile. Dans le cas extrême, une machine virtuelle qui n'a aucune information de trace de pile concernant ce thread est autorisée à renvoyer un tableau de longueur nulle à partir de cette méthode.

Bombe
la source
7
Ce même écueil est-il vrai pour les traces de pile dans les exceptions?
Nate Parsons
8
Oui, ça l'est. La documentation de Throwable . [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/… contient exactement le même paragraphe.
Bombe
4
La chose sous-jacente est que la JVM n'est pas tenue de fournir une trace de pile, mais que beaucoup de travail a été fait pour rendre HotSpot très fiable. Vous devez cependant savoir si vous souhaitez que votre code ne repose pas sur le comportement d'une machine virtuelle Java spécifique.
Thorbjørn Ravn Andersen
La version d'Alexsmail ci-dessous ne crée pas de trace de pile et vous donne accès à l'objet de méthode réel, pas seulement au nom (afin que vous puissiez également trouver le type de retour). Je n'ai pas de benchmark mais je soupçonne que sa méthode est beaucoup plus rapide car les traces de pile ont tendance à être chères.
Gus
La réponse de Devin semble donner une réponse beaucoup plus succincte à cette question.
relevantTide
310

Techniquement, cela fonctionnera ...

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

Cependant, une nouvelle classe interne anonyme sera créée pendant la compilation (par exemple YourClass$1.class). Cela va donc créer un .classfichier pour chaque méthode qui déploie cette astuce. De plus, une instance d'objet autrement inutilisée est créée à chaque appel pendant l'exécution. Donc, cela peut être une astuce de débogage acceptable, mais cela s'accompagne d'une surcharge importante.

Un avantage de cette astuce est que les getEncosingMethod()retours java.lang.reflect.Methodpeuvent être utilisés pour récupérer toutes les autres informations de la méthode, y compris les annotations et les noms de paramètres. Cela permet de distinguer des méthodes spécifiques du même nom (surcharge de méthode).

Notez que selon le JavaDoc de getEnclosingMethod()cette astuce ne devrait pas jeter unSecurityException car les classes internes doivent être chargées en utilisant le même chargeur de classe. Il n'est donc pas nécessaire de vérifier les conditions d'accès même si un responsable sécurité est présent.

Il est nécessaire d'utiliser getEnclosingConstructor()pour les constructeurs. Pendant les blocs en dehors des méthodes (nommées), getEnclosingMethod()retourne null.

Devin
la source
9
Cela ne vous donnera pas la méthode en cours d'exécution. Cela vous donnera cette méthode dans laquelle une classe anonyme / locale est définie. - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000
7
classe Local {}; Nom de chaîne = Local.class.getEnclosingMethod (). GetName ();
alexsmail
21
@ shrini1000 l'idée est d'utiliser cet extrait là où les informations sont nécessaires, et non de les mettre dans une routine de bibliothèque.
Thorbjørn Ravn Andersen
4
Merci pour les conseils ! Au lieu de créer un nouvel objet, utilisez simplement this.getClass (). GetEnclosingMethod (). GetName ();
Lilo
3
@Lilo incorrect. getEnclosingMethodobtient le nom de la méthode où la classe est définie. this.getClass()ne vous aidera pas du tout. @wutzebaer pourquoi en auriez-vous même besoin? Vous y avez déjà accès.
Hazel Troost
134

Janvier 2009:
Un code complet serait (à utiliser avec la mise en garde de @ Bombe à l'esprit):

/**
 * 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
}

Plus dans cette question .

Mise à jour de décembre 2011:

commentaires bleutés :

J'utilise JRE 6 et me donne un nom de méthode incorrect.
Ça marche si j'écrisste[2 + depth].getMethodName().

  • 0est getStackTrace(),
  • 1est getMethodName(int depth)et
  • 2 appelle la méthode.

virgo47 de réponse (upvoted) calcule effectivement l'index droit d'appliquer afin de récupérer le nom de la méthode.

VonC
la source
2
Il ne dit que "principal" pour moi. : - /
contrat du professeur Falken a été rompu
@Amigable: avez-vous essayé d'imprimer tout le StackTraceElementtableau à des fins de débogage et de voir si «principal» est réellement la bonne méthode?
VonC
7
J'utilise JRE 6 et me donne un nom de méthode incorrect. Cela fonctionne si j'écris ste[2 + depth].getMethodName(). 0 est getStackTrace(), 1 est getMethodName(int depth)et 2 appelle la méthode. Voir aussi la réponse de @ virgo47 .
bleuâtre
2
@bluish: bon point. J'ai inclus votre commentaire et une référence à la réponse de virgo47 dans la mienne.
VonC
@VonC Cette implémentation est-elle vraiment correcte? la profondeur ici doit être ste.length + 1 pour que cela donne la méthode actuelle. Ne doit-il pas être ste [profondeur + 1] si l'on veut permettre profondeur = 0?
mmm
85

Nous avons utilisé ce code pour atténuer la variabilité potentielle de l'index de trace de pile - appelez maintenant 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();
    }
}

Semble trop conçu, mais nous avions un certain nombre fixe pour JDK 1.5 et nous avons été un peu surpris que cela ait changé lorsque nous sommes passés à JDK 1.6. Maintenant, c'est la même chose en Java 6/7, mais on ne sait jamais. Ce n'est pas une preuve des changements dans cet index pendant l'exécution - mais j'espère que HotSpot ne fait pas si mal. :-)

virgo47
la source
1
Cela dépend toujours subtilement du fournisseur. La JVM n'est pas tenue de fournir des données fiables pour ce code.
Thorbjørn Ravn Andersen
6
Selon la spécification JVM, la JVM n'est pas tenue de fournir des traces de pile complètes (optimisation, inline et tout cela) et vous avez déjà découvert que votre heuristique a changé entre Oracle Java 5 et Oracle Java 6. Rien ne garantit que toute autre JVM comportez-vous comme prévu dans votre code, vous vous fiez donc subtilement au comportement spécifique du fournisseur. Ce qui est parfaitement bien, tant que vous en êtes conscient, mais si - par exemple - vous devez déployer sur une machine virtuelle Java IBM (ce que nous devons) ou sur une instance Zing, vous devrez peut-être revoir votre heuristique.
Thorbjørn Ravn Andersen
1
Cela semble la plus robuste de toutes les options présentées ici, malgré les dépendances.
Ian
46
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

nom aura une valeur foo.

alexsmail
la source
5
Local.class.getEnclosingMethod () était null. jdk1.6.0_31, jouer 1.2.5
eigil
@eigil c'est intéressant mais sans plus d'informations, il est difficile de dire ce qui s'est "mal" passé ou quand on devrait s'y attendrenull
Maarten Bodewes
C'est la même astuce que cette réponse . Il présente l'avantage de ne pas créer d'instance d'objet parasite, il présente l'inconvénient de nécessiter une déclaration de classe qui ne peut pas être insérée dans l'instruction (c'est-à-dire qu'il nécessite normalement une ligne de code supplémentaire).
Maarten Bodewes
@eigil avez-vous défini la classe dans une classe (exemple SomeClass), ou dans une méthode (exemple foo)? J'ai trouvé que la définition d'une sous-classe sans être enveloppée dans une méthode - ou dans un constructeur - entraînera le retour de null de getEnclosingMethod ().
DN
Je suis sûr que j'ai fait exactement comme décrit dans cette réponse. Je pense que c'est quelque chose d'étrange avec le cadre de jeu. Testé en java 'normal' sans aucun problème.
eigil
36

Ces deux options fonctionnent pour moi avec Java:

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

Ou:

Thread.currentThread().getStackTrace()[1].getMethodName()
Charlie Seligman
la source
1
pour les méthodes statiques, utilisez: <Class> .class.getEnclosingMethod (). getName ()
jellobird
attention au tableau vide selon la réponse de Bombe et l'indication javadoc. Certaines JVM peuvent ne pas remplir le tableau stacktrace?
el-teedee
34

Le moyen le plus rapide que j'ai trouvé est que:

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

Il accède directement à la méthode native getStackTraceElement (int depth). Et stocke la méthode accessible dans une variable statique.


la source
3
Le plus rapide comme en performance? Y a-t-il un micro-repère pour soutenir la réclamation?
Ibrahim Arief
10
+1. En utilisant une simple boucle chronométrée sur 1.6, 1 000 000 d'itérations utilisant cette méthode ont pris 1219 ms, tandis que l'utilisation a new Throwable().getStackTrace()pris 5614 ms.
ach
1
m.setAccessible (true); doit être entouré par AccessController.doPrivileged. Quelque chose à considérer, pas une règle
stricte,
6
Testé en 2016 et cela continue d'être le plus rapide. Comme @ach, j'ai utilisé 1M d'itérations. 1,7_79: 1,6 s contre 15,2 s 1,8_74: 1,8 s contre 16,0 s. FWIW la longueur de mon tableau de référence == 23 mais cette méthode reste rapide quelle que soit la profondeur de la pile.
Ryan
25

Utilisez le code suivant:

    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
    String methodName = e.getMethodName();
    System.out.println(methodName);
Sumit Singh
la source
2
Cela imprime "getStackTrace" pour moi - j'utilise Java 1.5
Zack Macomber
attention au tableau vide selon la réponse de Bombe et l'indication javadoc. Certaines JVM peuvent ne pas remplir le tableau stacktrace?
el-teedee
16
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }
Geai
la source
Oui, de loin le meilleur ... transformez-le en une méthode et obtenez la troisième ([2]) trame (ou son nom) dans la trace.
mike rodent
14

Ceci est une extension de la réponse de virgo47 (ci-dessus).

Il fournit des méthodes statiques pour obtenir les noms de classe / méthode actuels et appelants.

/* 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 + ")";
    }
}
mvanle
la source
3
Ceci en combinaison avec la réponse de @ mklemenz est un moyen très rapide et propre d'accéder aux informations de la pile.
Octavia Togami
12

Pour obtenir le nom de la méthode qui a appelé la méthode actuelle, vous pouvez utiliser:

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

Cela fonctionne sur mon MacBook ainsi que sur mon téléphone Android

J'ai aussi essayé:

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

mais Android retournera "getStackTrace". Je pourrais résoudre ce problème pour Android avec

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

mais je reçois la mauvaise réponse sur mon MacBook

Friso van der Made
la source
Lors de récents tests sur Android, il a mieux fonctionné pour moi getStackTrace()[0]plutôt que getStackTrace()[1]. YMMV.
mbm29414
pour Android estThread.currentThread().getStackTrace()[2]
Ninja
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
    }
}
Maxple
la source
final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; travaux; e.getClassName();retourne le nom complet de la classe et e.getMethodName()retourne le nom du méthon.
Marque
1
getStackTrace()[2]est faux, cela doit être getStackTrace()[3]dû au fait que: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] La fonction a () l'appelant
PhilLab
11

Cela peut être fait en utilisant StackWalkerdepuis 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();
}

StackWalkerest conçu pour être paresseux, il est donc probablement plus efficace que, par exemple, Thread.getStackTracequi crée avec impatience un tableau pour l'ensemble de la pile d'appels. Consultez également le JEP pour plus d'informations.

Radiodef
la source
5

Une autre méthode consiste à créer, mais pas à lever, une exception et à utiliser cet objet à partir duquel obtenir les données de trace de pile, car la méthode englobante sera généralement à l'index 0 - tant que la JVM stocke ces informations, comme d'autres l'ont fait. mentionné ci-dessus. Ce n'est cependant pas la méthode la moins chère.

De Throwable.getStackTrace () (c'est la même chose depuis Java 5 au moins):

L'élément zéro du tableau (en supposant que la longueur du tableau est non nulle) représente le haut de la pile, qui est la dernière invocation de méthode dans la séquence. En règle générale , c'est le point auquel ce jetable a été créé et lancé.

L'extrait ci-dessous suppose que la classe n'est pas statique (à cause de getClass ()), mais c'est un aparté.

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
Jool
la source
4
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
couru
la source
1
Voir les réponses de mvanle virgo47 ci-dessus et les commentaires de thorbjorn-ravn-andersen. Répétition, code imprécis et non fiable.
alexsmail
@ShivaKomuravelly Oui, mais il ne semble en aucun cas, donc -1 de moi aussi.
Maarten Bodewes
3

J'ai une solution en utilisant cela (dans 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())}));
    }
}
Kasim Rangwala
la source
3

Je ne sais pas quelle est l'intention derrière l'obtention du nom de la méthode actuellement exécutée, mais si c'est juste à des fins de débogage, les cadres de journalisation comme "logback" peuvent aider ici. Par exemple, lors de la déconnexion, tout ce que vous devez faire est d' utiliser le modèle "% M" dans votre configuration de journalisation . Cependant, cela doit être utilisé avec prudence car cela peut dégrader les performances.

James Selvakumar
la source
2

Juste au cas où la méthode dont vous voulez connaître le nom est une méthode de test junit, vous pouvez utiliser la règle junit TestName: https://stackoverflow.com/a/1426730/3076107

Egl
la source
1
@AndreiKonstantinov Je ne pense pas que ce soit uniquement un lien. Même si vous supprimez le lien, il reste au moins quelques informations à continuer.
EJoshuaS
1

La plupart des réponses ici semblent fausses.

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

Exemple:

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

Les sorties:

aaa  -> aaa
aaa  -> aaa
main -> main
mmm
la source
Merci pour votre réponse utile.
AmerllicA
Pourriez-vous préciser pourquoi la plupart des réponses vous semblent fausses? Il y a beaucoup de réponses et je ne connais pas très bien Java pour les lire toutes et comprendre quelle est la différence entre elles et votre réponse. :(
Xobotun
@mmm Désolé, mais je suis fortement en désaccord. Je viens ici pour apprendre et beaucoup d'autres aussi, je crois. Je ne comprends tout simplement pas pourquoi pensez-vous que je ne mérite pas d'en savoir plus à ce sujet. Je veux faire moins d'erreurs dans mon code et avertir les autres, ne pas suivre un culte du fret. Vous auriez pu au moins clarifier sur quelle version Java ce code devrait être correct. :( Une réponse ci-dessous dit qu'il y a eu un changement de stacktrace entre 1.5 et 1.6. Peut-être que vous impliquez qu'il y a quelque chose comme ça dans le prochain Java 14, comment puis-je le savoir. Ou un autre fournisseur peut avoir. Désolé si j'ai mal interprété votre réponse comme grossière un.
Xobotun
0

J'ai réécrit un peu la réponse du 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);
}
Marco Sulla
la source
-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
Darren
la source
11
Veuillez modifier avec plus d'informations. Les réponses de code uniquement et "essayez ceci" sont déconseillées, car elles ne contiennent aucun contenu consultable et n'expliquent pas pourquoi quelqu'un devrait "essayer ceci".
abarisone
1
Bien que ce code puisse aider à résoudre le problème, il n'explique pas pourquoi et / ou comment il répond à la question. Fournir ce contexte supplémentaire améliorerait considérablement sa valeur éducative à long terme. Veuillez modifier votre réponse pour ajouter des explications, y compris les limitations et hypothèses applicables.
Toby Speight
1
Uniquement pour Java 7+, mais un moyen concis pour obtenir le nom de la méthode. Reste tout de même les considérations de performances d'un tel appel.
Benj
6
getEnclosingMethod()lance un NullPointerExceptionpour moi dans Java 7.
Markus L
2
Java.lang.Class.getEnclosingMethod () renvoie un objet Method représentant la méthode immédiatement englobante de la classe sous-jacente, si cet objet Class représente une classe locale ou anonyme dans une méthode, sinon renvoie null.
poêle
-5

Quel est le problème avec cette approche:

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

Et avant que les gens ne deviennent fous de l'utilisation, System.out.println(...)vous pouvez toujours, et devriez, créer une méthode pour que la sortie puisse être redirigée, par exemple:

    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());
        }
    }
johnny
la source
4
@Saksham, il me semble que c'était en fait une tentative de répondre à la question. Pas une grande tentative, mais une tentative néanmoins.
ivarni
@ivarni "pas une bonne tentative"? Qu'est ce qui ne va pas avec ça? connaissez-vous le "principe du baiser"?
johnny
@Saksham c'était rhétorique.
johnny
5
@johnny Dans la base de code que j'ai devant moi en ce moment, il y a 271 classes. Même avec une (estimation basse) og 5 méthodes par classe, c'est plus de 1300 méthodes. Et ce n'est même pas une grosse base de code. Vous ne voyez pas le problème de l'extension de votre approche? Je suis très heureux d'accepter d'être en désaccord, mais c'est pourquoi j'ai dit que ce n'était pas une bonne tentative. Il introduit une énorme quantité de surcharge dans toute base de code non triviale.
ivarni
1
@johnny Je suppose que j'ai vu trop de cas où le nom de la méthode ne correspond pas à la chaîne qui m'a envoyé dans la mauvaise direction lors du débogage. Mais en Java, je pense toujours que votre suggestion est la meilleure, les autres alternatives "coûtent" trop cher.
Juste un autre métaprogrammeur