Отримання імені поточного способу виконання


Відповіді:


177

Thread.currentThread().getStackTrace()зазвичай міститиме метод, з якого ви його викликаєте, але є підводні камені (див. Javadoc ):

Деякі віртуальні машини за певних обставин можуть опускати один або кілька кадрів стека з сліду стека. У крайньому випадку віртуальній машині, яка не має інформації про сліди стека щодо цього потоку, дозволяється повертати масив нульової довжини з цього методу.


7
Чи справжній цей самий підводний камінь для слідів стека за винятками?
Нейт Парсонс

8
Так. Документація для Throwable . [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/… містить точно той самий абзац.
Bombe

4
Основна річ полягає в тому, що JVM не зобов'язаний забезпечити стек-трек, але багато роботи було зроблено, щоб зробити HotSpot дуже надійним. Але вам потрібно знати, якщо ви хочете, щоб ваш код не покладався на поведінку конкретного JVM.
Thorbjørn Ravn Andersen

Версія Alexsmail, наведена нижче, не створює стеження стека і надає вам доступ до фактичного об'єкта методу, а не лише до назви (так що ви також можете дізнатися тип повернення). Я не відзначився, але я підозрюю, що його метод набагато швидший, оскільки сліди стека, як правило, дорогі.
Гас

Відповідь Девіна, здається, дає значно кращішу відповідь на це питання.
підйомTide

310

Технічно це спрацює ...

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

Однак новий анонімний внутрішній клас буде створений під час компіляції (наприклад YourClass$1.class). Таким чином, це створить .classфайл для кожного методу, який розгортає цю хитрість. Додатково, інакше невикористаний екземпляр об'єкта створюється для кожного виклику під час виконання. Тож це може бути прийнятним налагодженням налагодження, але воно має значні накладні витрати.

Перевагою цього фокусу є те, що getEncosingMethod()повернення, java.lang.reflect.Methodякі можуть бути використані для отримання всієї іншої інформації методу, включаючи примітки та назви параметрів. Це дає можливість розрізняти конкретні методи з однойменною назвою (метод перевантаження).

Зауважте, що згідно з JavaDoc getEnclosingMethod()цей трюк не повинен кидати а, SecurityExceptionоскільки внутрішні класи повинні завантажуватися за допомогою того ж навантажувача класів. Тому немає необхідності перевіряти умови доступу, навіть якщо присутній менеджер безпеки.

Це потрібно використовувати getEnclosingConstructor()для конструкторів. Під час блоків поза (названими) методами getEnclosingMethod()повертається null.


9
Це не дасть вам поточного способу виконання. Це дасть вам той метод, у якому визначено анонімний / локальний клас. - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000

7
клас Local {}; Ім'я рядка = Local.class.getEnclosingMethod (). GetName ();
alexsmail

21
@ shrini1000 ідея полягає в тому, щоб використовувати цей фрагмент там, де потрібна інформація, а не вносити його в звичайну бібліотеку.
Thorbjørn Ravn Andersen

4
Дякую за поради! Замість створення нового об'єкта просто використовуйте this.getClass (). GetEnclosingMethod (). GetName ();
Ліло

3
@Lilo неправильно. getEnclosingMethodотримує назву методу, де визначено клас. this.getClass()зовсім не допоможе тобі. @wutzebaer навіщо вам це потрібно? Ви вже маєте доступ до них.
Hazel Troost

134

Січень 2009 р
. Повний код буде (використовувати на увазі застереження @ 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
}

Детальніше в цьому питанні .

Оновлення грудня 2011 року:

синюваті коментарі:

Я використовую JRE 6 і дає мені неправильну назву методу.
Це працює, якщо я пишуste[2 + depth].getMethodName().

  • 0є getStackTrace(),
  • 1є getMethodName(int depth)і
  • 2 є методом виклику.

virgo47 «s відповідь (upvoted) фактично обчислює вказівний застосовувати для того , щоб отримати назад назву методу.


2
Це говорить лише для мене "головне". : - /
Контракт проф. Фолкена порушено

@Amigable: ви намагалися надрукувати весь StackTraceElementмасив для налагодження і переконатися, що "main" насправді правильний метод?
VonC

7
Я використовую JRE 6 і дає мені неправильну назву методу. Це працює, якщо я пишу ste[2 + depth].getMethodName(). 0 є getStackTrace(), 1 є getMethodName(int depth)і 2 викликає метод. Дивіться також відповідь @ virgo47 .
синюватий

2
@bluish: хороший момент. Я включив ваш коментар і посилання на відповідь virgo47 у моєму.
VonC

@VonC Це дійсно правильна реалізація? Глибина тут повинна бути ste.length + 1, щоб дати поточний метод. Чи не слід це бути [глибина + 1], якщо ми повинні допустити глибину = 0?
ммм

85

Цей код ми використовували для зменшення потенційної мінливості в індексі відстеження стека - тепер просто виклик 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();
    }
}

Здається, перенапружений, але у нас був певний фіксований номер для JDK 1.5 і трохи здивований, що він змінився, коли ми перейшли на JDK 1.6. Тепер те саме в Java 6/7, але ви просто ніколи не знаєте. Це не є доказом змін цього індексу під час виконання - але, сподіваємось, HotSpot не робить це погано. :-)


1
Це все ще тонко залежить від постачальника. JVM не вимагає для надання достовірних даних для цього коду.
Thorbjørn Ravn Andersen

6
Згідно зі специфікацією JVM, JVM не вимагає надання повних слідів стека (оптимізація, вбудована лінія та все це), і ви вже виявили, що ваші евристичні змінилися між Oracle Java 5 та Oracle Java 6. Нічого не гарантує, що будь-який інший JVM буде поводьтеся так, як ви очікуєте у своєму коді, тому ви тонко покладаєтесь на поведінку конкретного постачальника. Що цілком чудово, якщо ви це знаєте, але якщо, наприклад, вам потрібно розгорнути на IBM JVM (що ми повинні) або на екземплярі Zing, вам, можливо, доведеться переглянути свій евристичний.
Thorbjørn Ravn Andersen

1
Це здається найбільш надійним з усіх варіантів, представлених тут, незалежно від залежностей.
Іван

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

ім'я матиме значення foo.


5
Local.class.getEnclosingMethod () було нульовим. jdk1.6.0_31, грати 1.2.5
eigil

@eigil, що цікаво, але без додаткової інформації важко сказати, що пішло "не так" або коли слід очікуватиnull
Maarten Bodewes

Це та сама хитрість, що і ця відповідь . Перевага полягає в тому, що він не створює помилковий екземпляр об'єкта, він недоліком є ​​те, що для нього потрібна декларація класу, яка не може бути вписана в операторі (тобто, як правило, потрібен додатковий рядок коду).
Maarten Bodewes

@eigil Ви визначили клас у класі (наприклад SomeClass) або в методі (на прикладі foo)? Я виявив, що визначення підкласу без загортання в метод - або в конструктор - призведе до повернення null getEnclosingMethod ().
DN

Досить впевнений, що я зробив саме так, як описано у цій відповіді. Я думаю, що це щось дивне з ігровими рамками. Тестується в 'нормальній' Java без проблем.
eigil

36

Обидва ці варіанти для мене працюють з Java:

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

Або:

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

1
для статичних методів використовуйте: <Class> .class.getEnclosingMethod (). getName ()
jellobird

будьте обережні до порожнього масиву відповідно до відповіді Бомбе та вказівки javadoc. Деякий JVM може не заповнити масив стека?
el-teedee

34

Найшвидший спосіб я знайшов:

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

Доступ до власного методу getStackTraceElement (глибина int) безпосередньо. І зберігає доступний метод у статичній змінній.


3
Найшвидший як у продуктивності? Будь-який мікро-орієнтир на підтримку претензії?
Ібрагім Короткий

10
+1. Використовуючи простий цикл з тимчасовим циклом на 1,6, 1 000 000 ітерацій за допомогою цього методу зайняли 1219 мс, а для використання - new Throwable().getStackTrace()5614 мс.
ач

1
m.setAccessible (вірно); повинні бути оточені AccessController.doPrivileged. Щось слід врахувати, не важке правило, яке я б сказав
avanderw

6
Випробували у 2016 році, і це продовжує бути найшвидшим. Як і @ach, я використовував 1M ітерації. 1,7_79: 1,6s проти 15,2s 1,8_74: 1,8s проти 16,0s. FWIW довжина мого еталону ste array == 23, але цей метод залишається швидким, незалежно від глибини стека.
Райан

25

Використовуйте наступний код:

    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
Це друкує для мене "getStackTrace" - я використовую Java 1.5
Zack Macomber

будьте обережні до порожнього масиву відповідно до відповіді Бомбе та вказівки javadoc. Деякий JVM може не заповнити масив стека?
el-teedee

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

Так, безумовно, найкраще ... перетворіть його на метод і отримайте третій ([2]) кадр (або як він ще називається) у трасі.
мійський гризун

14

Це розширення відповіді virgo47 (вище).

Він надає деякі статичні методи для отримання поточних і викликів імен класів / методів.

/* 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
Це в поєднанні з відповіддю @ mklemenz - це дуже швидкий і чистий спосіб доступу до інформації про стек.
Octavia Togami

12

Щоб отримати ім'я методу, який викликав поточний метод, ви можете використовувати:

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

Це працює як на моєму MacBook, так і на моєму телефоні Android

Я також спробував:

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

але Android поверне "getStackTrace", я можу це виправити для Android

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

але тоді я отримую неправильну відповідь на своєму MacBook


Під час останніх тестувань на Android мені було краще використовувати getStackTrace()[0], ніж використовувати getStackTrace()[1]. YMMV.
mbm29414

для 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
    }
}

final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; працює; e.getClassName();повернути повне ім'я класу та e.getMethodName()повернути ім'я метону.
Відзначається

1
getStackTrace()[2]неправильно, це має бути getStackTrace()[3]тому, що: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] Функція a () називає цю
PhilLab

11

Це можна зробити за допомогою 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();
}

StackWalkerрозроблений так, щоб бути ледачим, тому, швидше за все, він буде більш ефективним, ніж, скажімо, Thread.getStackTraceщо охоче створює масив для всього стовбука виклику. Також див. JEP для отримання додаткової інформації.


5

Альтернативний метод - створити, але не кидати, виняток, і використовувати той об'єкт, з якого можна отримати дані про стеження стека, оскільки метод укладання, як правило, буде в індексі 0 - доки JVM зберігає цю інформацію, як і інші вищезгаданий. Однак це не найдешевший метод.

Від Throwable.getStackTrace () (це було те саме з Java 5, принаймні):

Нульовий елемент масиву (якщо вважати, що довжина масиву не дорівнює нулю) представляє верхню частину стека, що є останнім викликом методу в послідовності. Як правило , це точка, в якій цю кинуту створювали і кидали.

Нижче наведений фрагмент передбачає, що клас нестатичний (через getClass ()), але це вбік.

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
Дивіться відповіді mvanle virgo47 вище та коментар thorbjorn-ravn-andersen. Повторення, неточний і ненадійний код.
alexsmail

@ShivaKomuravelly Так, але не в будь-якій ситуації, здається, так -1 від мене.
Maarten Bodewes

3

У мене є рішення, використовуючи це (В 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())}));
    }
}

3

Я не знаю, у чому полягає намір отримати ім'я виконуваного в даний час методу, але якщо це лише з метою налагодження, тут можуть допомогти реєстрації фреймів типу "logback". Наприклад, для зворотного зв'язку, все, що вам потрібно зробити, - це використовувати шаблон "% M" у своїй конфігурації реєстрації . Однак це слід використовувати обережно, оскільки це може погіршити продуктивність.


2

На випадок, якщо метод, який ви хочете знати, є методом тестування Джуніт, тоді ви можете використовувати правило junit TestName: https://stackoverflow.com/a/1426730/3076107


1
@AndreiKonstantinov Я не думаю, що це лише посилання. Навіть якщо ви видалите посилання, все одно є хоча б деяка інформація.
EJoshuaS

1

Більшість відповідей тут здається неправильним.

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

Приклад:

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

Виходи:

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

Дякуємо за вашу корисну відповідь.
AmerllicA

Не могли б ви пояснити, чому більшість відповідей здаються вам неправильними? Є багато відповідей, і я не так добре розбираюся в Java, щоб прочитати їх усі і зрозуміти, в чому різниця між ними та вашою відповіддю. :(
Xobotun

@mmm Вибачте, але я категорично не згоден. Я приходжу сюди, щоб вчитися, і так багато інших, я вважаю. Я просто не можу зрозуміти, чому ти вважаєш, що я не заслуговую на цю тему більше знати. Я хочу зробити менше помилок у своєму коді та попередити інших, а не дотримуватися деяких вантажних культів. Ви могли хоч би уточнити, на якій версії Java повинен бути правильним цей код. :( У відповіді нижче йдеться про зміну стек-траксів між 1,5 і 1,6. Можливо, ви маєте на увазі, що в майбутньому Java 14 щось подібне є, як я можу це знати. Або може виникнути інший постачальник. Вибачте, якщо я неправильно трактував вашу відповідь як грубувата. один.
Xobotun

0

Я трохи переписав відповідь маклеменса :

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
Відредагуйте додаткові відомості. Відповіді, що містять лише коди, та "спробувати це" не рекомендують, оскільки вони не містять вмісту, який можна шукати, і не пояснюють, чому хтось повинен "спробувати це".
абарізон

1
Хоча цей код може допомогти вирішити проблему, він не пояснює, чому та / або як він відповідає на питання. Забезпечення цього додаткового контексту значно покращило б його довгострокове навчальне значення. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення, включаючи, які обмеження та припущення застосовуються.
Toby Speight

1
Тільки для Java 7+, але стислий спосіб отримати ім'я методу. Все-таки залишаються міркування щодо виконання такого дзвінка.
Бендж

6
getEnclosingMethod()кидає NullPointerExceptionдля мене на Java 7.
Маркус Л

2
Java.lang.Class.getEnclosingMethod () повертає об'єкт Method, що представляє метод, що негайно закриває базовий клас, якщо цей об'єкт Class представляє локальний або анонімний клас у межах методу, інакше повертає null.
піч

-5

Що не так у цьому підході:

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

І перш ніж люди з глузду від використання System.out.println(...)вас можуть завжди, і повинні, створити якийсь метод, щоб результат можна було перенаправляти, наприклад:

    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 мені здається, що це насправді була спроба відповісти на питання. Не велика спроба, але все ж спроба.
ivarni

@ivarni "непогана спроба"? що не так з ним? ви знайомі з "принципом поцілунку"?
Джонні

@Saksham це було риторично.
Johnny

5
@johnny У кодовій базі я переді мною зараз 271 клас. Навіть із (низькою оцінкою) og 5 методів на клас, що становить понад 1300 методів. І це навіть не велика база коду. Ви не бачите проблеми зі збільшенням підходу? Я цілком радий погодитись не погодитись, але саме тому я сказав, що це не вдала спроба. Він вводить величезну кількість накладних витрат у будь-якій нетривіальній кодовій базі.
ivarni

1
@johnny Я думаю, я бачив занадто багато випадків, коли назва методу не відповідає рядку, який направив мене в неправильному напрямку при налагодженні. Але в Java я все ще думаю, що ваша пропозиція найкраща, інші альтернативи "коштують" занадто дорого.
Просто ще один метапрограміст
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.