Obtendo o nome do método atualmente em execução

470

Existe uma maneira de obter o nome do método atualmente em execução em Java?

Omar Kooheji
fonte

Respostas:

177

Thread.currentThread().getStackTrace()normalmente conterá o método do qual você está chamando, mas existem armadilhas (consulte Javadoc ):

Algumas máquinas virtuais podem, em algumas circunstâncias, omitir um ou mais quadros de pilha do rastreamento de pilha. No caso extremo, uma máquina virtual que não possui informações de rastreamento de pilha relacionadas a esse encadeamento tem permissão para retornar uma matriz de comprimento zero desse método.

Bombe
fonte
7
Essa mesma armadilha é verdadeira para rastreamentos de pilha em exceções?
Nate Parsons
8
Sim, ele é. A documentação para Throwable . [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/… contém exatamente o mesmo parágrafo.
Bombe
4
O essencial é que a JVM não precisa fornecer um rastreamento de pilha, mas muito trabalho foi feito para tornar o HotSpot muito confiável. Você precisa saber, no entanto, caso deseje que seu código não confie no comportamento de uma JVM específica.
Thorbjørn Ravn Andersen
A versão de Alexsmail abaixo não cria um rastreamento de pilha e fornece acesso ao objeto do método real, não apenas ao nome (para que você também possa descobrir o tipo de retorno). Não tenho marcação de banco, mas suspeito que o método dele seja muito mais rápido, já que os rastreamentos de pilha tendem a ser caros.
Gus
A resposta de Devin parece dar uma resposta muito mais sucinta a essa pergunta.
risingTide
310

Tecnicamente isso vai funcionar ...

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

No entanto, uma nova classe interna anônima será criada durante o tempo de compilação (por exemplo YourClass$1.class). Portanto, isso criará um .classarquivo para cada método que implanta esse truque. Além disso, uma instância de objeto não utilizada é criada em cada chamada durante o tempo de execução. Portanto, esse pode ser um truque de depuração aceitável, mas ele vem com uma sobrecarga significativa.

Uma vantagem desse truque é que getEncosingMethod()retornos java.lang.reflect.Methodpodem ser usados ​​para recuperar todas as outras informações do método, incluindo anotações e nomes de parâmetros. Isso torna possível distinguir entre métodos específicos com o mesmo nome (sobrecarga de método).

Observe que, de acordo com o JavaDoc getEnclosingMethod()deste truque, não deve ser lançado SecurityExceptioncomo as classes internas devem ser carregadas usando o mesmo carregador de classes. Portanto, não há necessidade de verificar as condições de acesso, mesmo se um gerente de segurança estiver presente.

É necessário usar getEnclosingConstructor()para construtores. Durante os blocos fora dos métodos (nomeados), getEnclosingMethod()retorna null.

Devin
fonte
9
Isso não fornecerá o método atualmente em execução. Isso fornecerá o método no qual uma classe local / anônima é definida. - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000
7
classe Local {}; Nome da string = Local.class.getEnclosingMethod (). GetName ();
Alexsmail
21
@ shrini1000 a idéia é usar esse trecho onde as informações são necessárias e não colocá-las na rotina da biblioteca.
Thorbjørn Ravn Andersen
4
Obrigado pelas dicas ! Em vez de criar um novo objeto, basta usar this.getClass (). GetEnclosingMethod (). GetName ();
Lilo
3
@Lilo incorreto. getEnclosingMethodobtém o nome do método em que a classe está definida. this.getClass()não vai te ajudar em nada. @wutzebaer Por que você precisaria? Você já tem acesso a eles.
Hazel Troost
134

Janeiro de 2009:
Um código completo seria (para usar com a advertência de @ 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
}

Mais nesta pergunta .

Atualização em dezembro de 2011:

comentários azulados :

Eu uso o JRE 6 e me fornece o nome do método incorreto.
Funciona se eu escreverste[2 + depth].getMethodName().

  • 0é getStackTrace(),
  • 1é getMethodName(int depth)e
  • 2 está invocando método.

virgo47 's resposta (upvoted) realmente calcula o índice direito de aplicar a fim de obter de volta o nome do método.

VonC
fonte
2
Diz apenas "principal" para mim. : - /
Contrato do Prof. Falken violado
@ Amigable: você tentou imprimir toda a StackTraceElementmatriz para fins de depuração e ver se 'main' é realmente o método certo?
VonC 25/05
7
Eu uso o JRE 6 e me fornece o nome do método incorreto. Funciona se eu escrever ste[2 + depth].getMethodName(). 0 é getStackTrace(), 1 é getMethodName(int depth)e 2 está chamando o método. Veja também a resposta de @ virgo47 .
azulada
2
@ bluish: bom ponto. Incluí seu comentário e uma referência à resposta de virgo47 na minha.
VonC
@VonC Esta implementação está realmente correta? a profundidade aqui deve ser ste.length + 1 para que isso dê o método atual. Não deveria ser ste [profundidade + 1] se quisermos permitir profundidade = 0?
mmm
85

Usamos esse código para reduzir a variabilidade potencial no índice de rastreamento de pilha - agora basta chamar 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();
    }
}

Parece ser superengenharia, mas tínhamos um número fixo para o JDK 1.5 e ficamos um pouco surpresos ao mudar quando mudamos para o JDK 1.6. Agora é o mesmo no Java 6/7, mas você nunca sabe. Não é prova de alterações nesse índice durante o tempo de execução - mas espero que o HotSpot não seja tão ruim assim. :-)

virgo47
fonte
1
Isso ainda depende sutilmente do fornecedor. A JVM não é obrigada a fornecer dados confiáveis ​​para esse código.
Thorbjørn Ravn Andersen
6
De acordo com as especificações da JVM, a JVM não é obrigada a fornecer rastreamentos de pilha completos (otimização, inlining e tudo isso) e você já descobriu que sua heurística mudou entre o Oracle Java 5 e o Oracle Java 6. Não há nada que garanta que qualquer outra JVM se comporte conforme o esperado em seu código, portanto, você depende sutilmente do comportamento específico do fornecedor. O que é perfeitamente correto, desde que você esteja ciente disso, mas se, por exemplo, precisar implantar em uma IBM JVM (que devemos) ou em uma instância Zing, talvez seja necessário revisar sua heurística.
Thorbjørn Ravn Andersen
1
Essa parece ser a mais robusta de todas as opções apresentadas aqui, apesar das dependências.
Ian
46
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

nome terá valor foo.

alexsmail
fonte
5
Local.class.getEnclosingMethod () era nulo. jdk1.6.0_31, jogo 1.2.5
eigil 29/11
@eigil isso é interessante, mas sem mais informações, é difícil dizer o que deu "errado" ou quando devemos esperarnull
Maarten Bodewes
Este é o mesmo truque que esta resposta . Tem a vantagem de não criar uma instância de objeto espúrio, tem a desvantagem de exigir uma declaração de classe que não possa ser incorporada na instrução (ou seja, normalmente requer uma linha de código adicional).
Maarten Bodewes
@eigil você definiu a classe dentro de uma classe (exemplo SomeClass) ou dentro de um método (exemplo foo)? Eu descobri que definir uma subclasse sem ser envolvido em um método - ou em um construtor - fará com que getEnclosingMethod () retorne nulo.
DN
Tenho certeza de que fiz exatamente como descrito nesta resposta. Eu acho que é algo estranho com playframework. Testado em java 'normal' sem nenhum problema.
Eigil
36

Ambas as opções funcionam para mim com Java:

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

Ou:

Thread.currentThread().getStackTrace()[1].getMethodName()
Charlie Seligman
fonte
1
para métodos estáticos, use: <Class> .class.getEnclosingMethod (). getName ()
jellobird
tenha cuidado com a matriz vazia de acordo com a resposta de Bombe e a indicação javadoc. Algumas JVM podem não preencher a matriz de stacktrace?
El-teedee
34

A maneira mais rápida que encontrei é:

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

Ele acessa o método nativo getStackTraceElement (int depth) diretamente. E armazena o método acessível em uma variável estática.


fonte
3
Mais rápido como no desempenho? Alguma micro-referência para apoiar a reivindicação?
Ibrahim Arief
10
+1. Usando um loop cronometrado simples em 1,6, 1.000.000 de iterações usando esse método levaram 1219ms, enquanto o uso new Throwable().getStackTrace()levou 5614ms.
ach 25/01
1
m.setAccessible (verdadeiro); deve estar cercado por AccessController.doPrivileged. Algo a considerar, não é uma regra difícil, eu diria
avanderw
6
Testado em 2016 e este continua sendo o mais rápido. Como @ach, usei 1M de iterações. 1.7_79: 1.6s vs 15.2s 1.8_74: 1.8s vs 16.0s. FWIW o comprimento da matriz ste de referência == 23, mas esse método permanece rápido, independentemente da profundidade da pilha.
Ryan
25

Use o seguinte código:

    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
fonte
2
Isso imprime "getStackTrace" para mim - eu estou usando Java 1.5
Zack Macomber
tenha cuidado com a matriz vazia de acordo com a resposta de Bombe e a indicação javadoc. Algumas JVM podem não preencher a matriz de stacktrace?
El-teedee
16
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }
Jay
fonte
Sim, de longe o melhor ... transforme-o em um método e obtenha o terceiro ([2]) quadro (ou o que for chamado) no rastreamento.
mike roedor
14

Esta é uma expansão da resposta de virgo47 (acima).

Ele fornece alguns métodos estáticos para obter os nomes de classe / método atuais e invocadores.

/* 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
fonte
3
Isso em combinação com a resposta do @ mklemenz é uma maneira muito rápida e limpa de acessar as informações da pilha.
Octavia Togami
12

Para obter o nome do método que chamou o método atual, você pode usar:

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

Isso funciona no meu MacBook e no meu telefone Android

Eu também tentei:

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

mas o Android retornará "getStackTrace". Eu poderia corrigir isso no Android com

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

mas então eu recebo a resposta errada no meu MacBook

Friso van der Made
fonte
Em testes recentes no Android, que funcionou melhor para mim usar getStackTrace()[0], em vez de getStackTrace()[1]. YMMV.
mbm29414
para o Android éThread.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
fonte
final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; trabalho; e.getClassName();retorne o nome completo da classe e e.getMethodName()retorne o nome methon.
Marcas
1
getStackTrace()[2]está errado, deve ser getStackTrace()[3]porque: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] A função a () chamando este
PhilLab
11

Isso pode ser feito usando o StackWalkerJava 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();
}

StackWalkerfoi projetado para ser preguiçoso, então é provável que seja mais eficiente do que, digamos, o Thread.getStackTraceque cria ansiosamente uma matriz para todo o callstack. Veja também o JEP para mais informações.

Radiodef
fonte
5

Um método alternativo é criar, mas não lançar, uma exceção e usar esse objeto do qual obter os dados de rastreamento de pilha, pois o método envolvente estará normalmente no índice 0 - desde que a JVM armazene essas informações, como outros Mencionado acima. Este não é o método mais barato, no entanto.

De Throwable.getStackTrace () (isso é o mesmo desde o Java 5, pelo menos):

O elemento zeroth da matriz (assumindo que o comprimento da matriz é diferente de zero) representa o topo da pilha, que é a última invocação do método na sequência. Normalmente , este é o ponto em que esse lançamento foi criado e lançado.

O snippet abaixo assume que a classe não é estática (por causa de getClass ()), mas isso é um aparte.

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
Jool
fonte
4
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
correu
fonte
1
Veja as respostas de mvanle virgo47 acima e o comentário de thorbjorn-ravn-andersen. Código de repetição, não preciso e não confiável.
alexsmail
@ShivaKomuravelly Sim, mas não em nenhuma situação que pareça, então -1 de mim também.
Maarten Bodewes
3

Eu tenho solução usando isso (no 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
fonte
3

Não sei qual é a intenção por trás do nome do método atualmente executado, mas se isso for apenas para fins de depuração, as estruturas de log como "logback" podem ajudar aqui. Por exemplo, no logback, tudo que você precisa fazer é usar o padrão "% M" na sua configuração de log . No entanto, isso deve ser usado com cuidado, pois isso pode prejudicar o desempenho.

James Selvakumar
fonte
2

Caso o método que você deseja saber seja um método de teste de junit, você poderá usar a regra TestName de junit: https://stackoverflow.com/a/1426730/3076107

Egl
fonte
1
@AndreiKonstantinov Eu não acho que isso seja apenas um link. Mesmo se você remover o link, ainda há pelo menos algumas informações para continuar.
EJoshuaS - Restabelece Monica
1

A maioria das respostas aqui parece errada.

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

Exemplo:

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

Saídas:

aaa  -> aaa
aaa  -> aaa
main -> main
mmm
fonte
Obrigado pela sua resposta útil.
AmerllicA
Você poderia esclarecer por que a maioria das respostas parece errada para você? Existem muitas respostas e eu não sou tão versado em Java para ler todas elas e entender qual é a diferença entre elas e sua resposta. :(
Xobotun
@mmm Desculpe, mas eu discordo totalmente. Eu venho aqui para aprender e muitos outros, acredito. Só não consigo entender por que você acha que não mereço saber mais sobre esse assunto. Quero cometer menos erros no meu código e avisar os outros, para não seguir algum culto à carga. Você poderia pelo menos ter esclarecido em qual versão do Java esse código deve estar correto. :( Uma resposta abaixo diz que houve uma alteração no stacktrace entre 1,5 e 1,6. Talvez você implique que exista algo parecido no próximo Java 14, como posso saber. Ou outro fornecedor pode ter. Desculpe se interpretou mal sua resposta como rude um.
Xobotun
0

Reescrevi um pouco a resposta do 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
fonte
-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
Darren
fonte
11
Edite com mais informações. As respostas somente código e "tente isso" são desencorajadas, pois não contêm conteúdo pesquisável e não explicam por que alguém deveria "tentar fazer isso".
abarisone 27/09/16
1
Embora esse código possa ajudar a resolver o problema, ele não explica por que e / ou como responde à pergunta. Fornecer esse contexto adicional melhoraria significativamente seu valor educacional a longo prazo. Por favor edite sua resposta para adicionar explicação, incluindo o que limitações e premissas se aplicam.
Toby Speight
1
Somente para Java 7+, mas maneira concisa de obter o nome do método. Ainda assim, permanecem as considerações de desempenho dessa chamada.
21416 Benj
6
getEnclosingMethod()lança um NullPointerExceptionpara mim em Java 7.
Markus L
2
O java.lang.Class.getEnclosingMethod () retorna um objeto Method que representa o método que encerra imediatamente a classe subjacente, se esse objeto Class representa uma classe local ou anônima dentro de um método, então retorna nulo.
fogão
-5

O que há de errado com essa abordagem:

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 antes que as pessoas fiquem loucas por usar, System.out.println(...)você sempre pode e deve criar algum método para que a saída possa ser redirecionada, por exemplo:

    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
fonte
4
@Saksham, parece-me que foi realmente uma tentativa de responder à pergunta. Não é uma grande tentativa, mas uma tentativa, no entanto.
Ivarni
@ivarni "não é uma boa tentativa"? O que há de errado com isso? você conhece o "princípio do beijo"?
johnny
@Saksham era retórico.
johnny
5
@johnny Na base de código que tenho na minha frente, agora existem 271 classes. Mesmo com uma (estimativa baixa) e 5 métodos por classe, são mais de 1300 métodos. E essa nem é uma grande base de código. Você não vê o problema de expandir sua abordagem? Fico feliz em concordar em discordar, mas foi por isso que disse que não é uma boa tentativa. Introduz uma enorme quantidade de sobrecarga em qualquer base de código não trivial.
Ivarni
1
@ johnny Eu acho que já vi muitos casos em que o nome do método não corresponde à string que me enviou na direção errada durante a depuração. Mas em Java ainda acho que sua sugestão é a melhor, as outras alternativas "custam" demais.
Apenas mais um metaprogramador.