Obtener el nombre del método actualmente en ejecución

470

¿Hay alguna manera de obtener el nombre del método que se está ejecutando actualmente en Java?

Omar Kooheji
fuente

Respuestas:

177

Thread.currentThread().getStackTrace()generalmente contendrá el método desde el que lo está llamando, pero existen dificultades (consulte Javadoc ):

Algunas máquinas virtuales pueden, en algunas circunstancias, omitir uno o más marcos de pila de la traza de pila. En el caso extremo, una máquina virtual que no tiene información de seguimiento de pila relacionada con este subproceso puede devolver una matriz de longitud cero de este método.

Bombe
fuente
77
¿Es cierto este mismo escollo para los seguimientos de pila en excepciones?
Nate Parsons
8
Sí lo es. La documentación de Throwable . [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/… contiene exactamente el mismo párrafo.
Bombe
44
Lo subyacente es que no se requiere que la JVM pueda proporcionar un seguimiento de la pila, pero que se ha invertido mucho trabajo para hacer que HotSpot sea muy confiable. Sin embargo, debe saber si desea que su código no se base en el comportamiento de una JVM específica.
Thorbjørn Ravn Andersen
La versión de Alexsmail a continuación no crea un seguimiento de la pila y le da acceso al objeto del método real, no solo al nombre (para que también pueda encontrar el tipo de retorno). No he marcado el banco, pero sospecho que su método es mucho más rápido, ya que los seguimientos de pila tienden a ser caros.
Gus
La respuesta de Devin parece dar una respuesta mucho más sucinta a esta pregunta.
risingTide
310

Técnicamente esto funcionará ...

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

Sin embargo, se creará una nueva clase interna anónima durante el tiempo de compilación (por ejemplo YourClass$1.class). Entonces esto creará un .classarchivo para cada método que despliegue este truco. Además, se crea una instancia de objeto no utilizada en cada invocación durante el tiempo de ejecución. Por lo tanto, este puede ser un truco de depuración aceptable, pero viene con una sobrecarga significativa.

Una ventaja de este truco es que los getEncosingMethod()retornos java.lang.reflect.Methodse pueden usar para recuperar toda la otra información del método, incluidas las anotaciones y los nombres de los parámetros. Esto permite distinguir entre métodos específicos con el mismo nombre (sobrecarga de métodos).

Tenga en cuenta que de acuerdo con el JavaDoc de getEnclosingMethod()este truco no se debe lanzar un SecurityExceptionya que las clases internas deben cargarse utilizando el mismo cargador de clases. Por lo tanto, no es necesario verificar las condiciones de acceso incluso si hay un administrador de seguridad presente.

Se requiere su uso getEnclosingConstructor()para constructores. Durante los bloques fuera de los métodos (con nombre), getEnclosingMethod()regresa null.

Devin
fuente
99
Esto no le dará el método de ejecución actual. Esto le dará ese método en el que se define una clase anónima / local. - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000
77
clase Local {}; Nombre de cadena = Local.class.getEnclosingMethod (). GetName ();
alexsmail
21
@ shrini1000, la idea es usar este fragmento donde se necesita la información, y no ponerlo en una rutina de biblioteca.
Thorbjørn Ravn Andersen
44
Gracias por los consejos ! En lugar de crear un nuevo objeto, simplemente use this.getClass (). GetEnclosingMethod (). GetName ();
Lilo
3
@Lilo incorrecto. getEnclosingMethodobtiene el nombre del método donde se define la clase. this.getClass()no te ayudará en absoluto. @wutzebaer, ¿por qué lo necesitarías? Ya tienes acceso a ellos.
Hazel Troost
134

Enero de 2009:
un código completo sería (para usar con la advertencia de @Bombe en mente):

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

Más en esta pregunta .

Actualización de diciembre de 2011:

comentarios azulados :

Yo uso JRE 6 y me da un nombre de método incorrecto.
Funciona si escriboste[2 + depth].getMethodName().

  • 0es getStackTrace(),
  • 1es getMethodName(int depth)y
  • 2 Es un método de invocación.

virgo47 's respuesta (upvoted) en realidad calcula el índice derecho de aplicar con el fin de recuperar el nombre del método.

VonC
fuente
2
Solo dice "principal" para mí. : - /
contrato del Prof. Falken incumplió
@Amigable: ¿trataste de imprimir todo el StackTraceElementarreglo para propósitos de depuración y ver si 'main' es realmente el método correcto?
VonC
77
Yo uso JRE 6 y me da un nombre de método incorrecto. Funciona si escribo ste[2 + depth].getMethodName(). 0 es getStackTrace(), 1 es getMethodName(int depth)y 2 es un método de invocación. Ver también la respuesta de @ virgo47 .
azulado
2
@ azulado: buen punto. He incluido tu comentario y una referencia a la respuesta de virgo47 en la mía.
VonC
@VonC ¿Es esta implementación realmente correcta? la profundidad aquí debe ser ste.length + 1 para que se obtenga el método actual. ¿No debería ser ste [profundidad + 1] si vamos a permitir profundidad = 0?
mmm
85

Utilizamos este código para mitigar la variabilidad potencial en el índice de seguimiento de la pila; ahora solo llame a 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 un exceso de ingeniería, pero teníamos un número fijo para JDK 1.5 y nos sorprendió un poco que cambiara cuando nos mudamos a JDK 1.6. Ahora es lo mismo en Java 6/7, pero nunca se sabe. No es una prueba de los cambios en ese índice durante el tiempo de ejecución, pero espero que HotSpot no lo haga tan mal. :-)

virgo47
fuente
1
Esto todavía depende sutilmente del proveedor. No se requiere que JVM entregue datos confiables para este código.
Thorbjørn Ravn Andersen
66
Según las especificaciones de JVM, no se requiere que JVM proporcione rastros completos de la pila (optimización, alineación y todo eso) y ya ha descubierto que su heurística cambió entre Oracle Java 5 y Oracle Java 6. No hay nada que garantice que cualquier otra JVM lo haga. comportarse como espera en su código, por lo que confía sutilmente en el comportamiento específico del proveedor. Lo cual está perfectamente bien, siempre que sea consciente de eso, pero si, por ejemplo, necesita implementar en un IBM JVM (que debemos) o en una instancia de Zing, puede que tenga que volver a visitar su heurística.
Thorbjørn Ravn Andersen
1
Esta parece la más robusta de todas las opciones presentadas aquí, a pesar de las dependencias.
Ian
46
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

nombre tendrá valor foo.

alexsmail
fuente
55
Local.class.getEnclosingMethod () era nulo. jdk1.6.0_31, juega 1.2.5
eigil
@eigil eso es interesante pero sin más información es difícil saber qué salió "mal" o cuándo deberíamos esperarnull
Maarten Bodewes
Este es el mismo truco que esta respuesta . Tiene la ventaja de que no crea una instancia de objeto espuria, tiene la desventaja de que requiere una declaración de clase que no se puede incluir en la declaración (es decir, normalmente requiere una línea de código adicional).
Maarten Bodewes
@eigil, ¿definiste la clase dentro de una clase (ejemplo SomeClass) o dentro de un método (ejemplo foo)? Descubrí que definir una subclase sin estar envuelto en un método, o en un constructor, hará que getEnclosingMethod () devuelva nulo.
DN
Estoy bastante seguro de que hice exactamente lo que se describe en esta respuesta. Creo que es algo extraño con playframework. Probado en Java 'normal' sin ningún problema.
eigil
36

Ambas opciones me funcionan con Java:

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

O:

Thread.currentThread().getStackTrace()[1].getMethodName()
Charlie Seligman
fuente
1
para métodos estáticos use: <Class> .class.getEnclosingMethod (). getName ()
jellobird
tenga cuidado con la matriz vacía de acuerdo con la respuesta de Bombe y la indicación javadoc. ¿Es posible que algunas JVM no llenen la matriz stacktrace?
el-teedee
34

La forma más rápida que encontré es 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;
        }
    }
}

Accede directamente al método nativo getStackTraceElement (int profundidad). Y almacena el Método accesible en una variable estática.


fuente
3
¿Más rápido que en cuanto a rendimiento? ¿Algún micro punto de referencia para respaldar el reclamo?
Ibrahim Arief
10
+1. Usando un bucle temporizado simple en 1.6, 1,000,000 de iteraciones usando este método tomaron 1219ms, mientras que el uso new Throwable().getStackTrace()tomó 5614ms.
ach
1
m.setAccessible (verdadero); debe estar rodeado por AccessController.doPrivileged. Algo a considerar, no es una regla difícil, diría
avanderw
66
Probado en 2016 y este sigue siendo el más rápido. Al igual que @ach, usé 1M de iteraciones. 1.7_79: 1.6s vs 15.2s 1.8_74: 1.8s vs 16.0s. FWIW mi benchmark ste array's length == 23 pero este método se mantiene rápido independientemente de la profundidad de la pila.
Ryan
25

Use el siguiente 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
fuente
2
Esto imprime "getStackTrace" para mí - Estoy usando Java 1.5
Zack Macomber
tenga cuidado con la matriz vacía de acuerdo con la respuesta de Bombe y la indicación javadoc. ¿Es posible que algunas JVM no llenen la matriz stacktrace?
el-teedee
16
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }
Arrendajo
fuente
Sí, de lejos el mejor ... conviértalo en un método y obtenga el tercer marco ([2]) (o como se llame) en la traza.
Mike roedor
14

Esta es una expansión de la respuesta de virgo47 (arriba).

Proporciona algunos métodos estáticos para obtener los nombres de clase / método actuales 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
fuente
3
Esto en combinación con la respuesta de @ mklemenz es una forma muy rápida y limpia de acceder a la información de la pila.
Octavia Togami
12

Para obtener el nombre del método que llamó al método actual, puede usar:

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

Esto funciona en mi MacBook y en mi teléfono Android

También probé:

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

pero Android devolverá "getStackTrace". Podría arreglar esto para Android con

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

pero luego recibo la respuesta incorrecta en mi MacBook

Friso van der Made
fuente
En pruebas recientes en Android, funcionó mejor para mí usar en getStackTrace()[0]lugar de getStackTrace()[1]. YMMV.
mbm29414
para Android esThread.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
fuente
final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; trabajos; e.getClassName();devolver el nombre completo de la clase y e.getMethodName()devolver el nombre del methon.
Marcas
1
getStackTrace()[2]está mal, tiene que ser getStackTrace()[3]porque: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] La función a () llamando a este
PhilLab
11

Esto se puede hacer StackWalkerdesde 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á diseñado para ser perezoso, por lo que es probable que sea más eficiente que, por ejemplo, Thread.getStackTraceque crea ansiosamente una matriz para toda la pila de llamadas. También vea el JEP para más información.

Radiodef
fuente
5

Un método alternativo es crear, pero no lanzar, una Excepción, y usar ese objeto desde el cual obtener los datos de seguimiento de la pila, ya que el método de inclusión generalmente estará en el índice 0, siempre que la JVM almacene esa información, como lo han hecho otros. mencionado anteriormente. Sin embargo, este no es el método más barato.

Desde Throwable.getStackTrace () (esto ha sido lo mismo desde Java 5 al menos):

El elemento cero de la matriz (suponiendo que la longitud de la matriz no es cero) representa la parte superior de la pila, que es la última invocación de método en la secuencia. Por lo general , este es el punto en el que este lanzamiento se creó y se lanzó.

El fragmento a continuación asume que la clase no es estática (debido a getClass ()), pero eso es un aparte.

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
Jool
fuente
4
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
corrió
fuente
1
Ver las respuestas de mvanle virgo47 arriba y comentarios de thorbjorn-ravn-andersen. Repetición, código no preciso y no confiable.
alexsmail
@ShivaKomuravelly Sí, pero en ninguna situación parece, así que -1 de mí también.
Maarten Bodewes
3

Tengo una solución usando esto (en 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
fuente
3

No sé cuál es la intención detrás de obtener el nombre del método ejecutado actualmente, pero si eso es solo para fines de depuración, entonces los marcos de registro como "logback" pueden ayudar aquí. Por ejemplo, en el inicio de sesión, todo lo que necesita hacer es usar el patrón "% M" en su configuración de registro . Sin embargo, esto debe usarse con precaución ya que puede degradar el rendimiento.

James Selvakumar
fuente
2

En caso de que el método cuyo nombre desea saber sea un método de prueba junit, puede usar la regla Junit TestName: https://stackoverflow.com/a/1426730/3076107

Egl
fuente
1
@AndreiKonstantinov No creo que esto sea solo de enlace. Incluso si elimina el enlace, todavía hay al menos algo de información para continuar.
EJoshuaS - Restablece a Monica
1

La mayoría de las respuestas aquí parecen incorrectas.

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

Ejemplo:

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

Salidas:

aaa  -> aaa
aaa  -> aaa
main -> main
mmm
fuente
Gracias por tu útil respuesta.
AmerllicA
¿Podría aclarar por qué la mayoría de las respuestas le parecen incorrectas? Hay muchas respuestas y no estoy muy versado en Java para leerlas todas y entender cuál es la diferencia entre ellas y su respuesta. :(
Xobotun
@mmm Lo siento, pero estoy totalmente en desacuerdo. Vengo aquí para aprender y muchos otros, creo. Simplemente no puedo entender por qué crees que no merezco saber más sobre este tema. Quiero cometer menos errores en mi código y advertir a otros, no seguir un culto a la carga. Al menos podría haber aclarado en qué versión de Java este código debería ser correcto. :( Una respuesta a continuación dice que hubo un cambio en el stacktrace entre 1.5 y 1.6. Tal vez insinúes que hay algo así en el próximo Java 14, ¿cómo puedo saberlo? uno.
Xobotun
0

Reescribí un poco la respuesta de 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
fuente
-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
Darren
fuente
11
Edite con más información. Se desaconsejan las respuestas de solo código y "pruebe esto", ya que no contienen contenido que se pueda buscar y no explican por qué alguien debería "probar esto".
abarisone
1
Aunque este código puede ayudar a resolver el problema, no explica por qué y / o cómo responde la pregunta. Proporcionar este contexto adicional mejoraría significativamente su valor educativo a largo plazo. Por favor, editar su respuesta para agregar explicación, incluyendo lo que se aplican limitaciones y supuestos.
Toby Speight
1
Solo para Java 7+, pero es una forma concisa de obtener el nombre del método. Aún así, sigue siendo las consideraciones de rendimiento de tal llamada.
Benj
66
getEnclosingMethod()lanza un NullPointerExceptionpara mí en Java 7.
Markus L
2
Java.lang.Class.getEnclosingMethod () devuelve un objeto Method que representa el método de cierre inmediato de la clase subyacente, si este objeto Class representa una clase local o anónima dentro de un método, de lo contrario devuelve nulo.
estufa
-5

¿Qué tiene de malo este enfoque?

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

Y antes de que la gente se vuelva loca por el uso System.out.println(...), siempre podría y debería crear algún método para que la salida se pueda redirigir, por ejemplo:

    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
fuente
44
@Saksham me parece que en realidad fue un intento de responder la pregunta. No es un gran intento, pero un intento no obstante.
ivarni
@ivarni "no es un buen intento"? ¿Qué tiene de malo? ¿Conoces el "principio del beso"?
Johnny
@Saksham fue retórico.
Johnny
55
@johnny En la base de código que tengo frente a mí en este momento hay 271 clases. Incluso con una (estimación baja) de 5 métodos por clase que supera los 1300 métodos. Y esto ni siquiera es una gran base de código. ¿No ve el problema de ampliar su enfoque? Estoy muy contento de aceptar estar en desacuerdo, pero por eso dije que no es un buen intento. Introduce una cantidad masiva de sobrecarga en cualquier base de código no trivial.
ivarni
1
@johnny Supongo que he visto demasiados casos en los que el nombre del método no coincide con la cadena que me ha enviado en la dirección incorrecta al depurar. Pero en Java todavía creo que su sugerencia es la mejor, las otras alternativas "cuestan" demasiado.
Solo otro metaprogramador