【问题标题】:Getting the name of the currently executing method获取当前执行方法的名称
【发布时间】:2010-10-01 08:40:18
【问题描述】:

有没有办法在 Java 中获取当前正在执行的方法的名称?

【问题讨论】:

    标签: java reflection methods


    【解决方案1】:

    从技术上讲,这会起作用...

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

    但是,在编译期间将创建一个新的匿名内部类(例如YourClass$1.class)。因此,这将为部署此技巧的每个方法创建一个.class 文件。此外,在运行时每次调用时都会创建一个未使用的对象实例。所以这可能是一个可以接受的调试技巧,但它确实会带来很大的开销。

    此技巧的一个优点是getEnclosingMethod() 返回java.lang.reflect.Method,可用于检索方法的所有其他信息,包括注释和参数名称。这使得区分具有相同名称的特定方法成为可能(方法重载)。

    请注意,根据getEnclosingMethod() 的JavaDoc,此技巧不应抛出SecurityException,因为应使用相同的类加载器加载内部类。因此,即使有安全管理员,也无需检查访问条件。

    请注意:构造函数必须使用getEnclosingConstructor()。在(命名的)方法之外的块期间,getEnclosingMethod() 返回null

    【讨论】:

    • 这不会给你当前正在执行的方法。这将为您提供定义匿名/本地类的方法。 - docs.oracle.com/javase/6/docs/api/java/lang/…
    • 类本地{};字符串名称 = Local.class.getEnclosureMethod().getName();
    • @shrini1000 这个想法是在需要信息的地方使用这个 sn-p,而不是将其放入库例程中。
    • 感谢您的提示!不用创建新对象,只需使用 this.getClass().getEnclosureMethod().getName();
    • @Lilo 不正确。 getEnclosingMethod 获取定义类的方法的名称。 this.getClass() 根本不会帮助你。 @wutzebaer 为什么你甚至需要?您已经可以访问它们了。
    【解决方案2】:

    @987654321@.@987654322@.@987654323@ 通常会包含您从中调用它的方法,但存在缺陷(请参阅Javadoc):

    在某些情况下,某些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧。在极端情况下,允许没有关于该线程的堆栈跟踪信息的虚拟机从该方法返回一个长度为零的数组。

    【讨论】:

    • 异常中的堆栈跟踪是否存在同样的陷阱?
    • 是的。 Throwable.[getStackTrace()](download.oracle.com/javase/1.5.0/docs/api/java/lang/… 的文档包含完全相同的段落。
    • 基本情况是 JVM 不是必需 能够提供堆栈跟踪,但是为了使 HotSpot 非常可靠,我们做了很多工作。但是,您需要知道,以防您希望您的代码不依赖于特定 JVM 的行为。
    • Alexsmail 的以下版本不会创建堆栈跟踪,并允许您访问实际的方法对象,而不仅仅是名称(因此您也可以找出返回类型)。我没有进行基准测试,但我怀疑他的方法也快得多,因为堆栈跟踪往往很昂贵。
    【解决方案3】:

    2009 年 1 月:
    完整的代码将是(与 @Bombe's caveat 一起使用):

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

    更多内容请关注this question

    2011 年 12 月更新:

    bluishcmets:

    我使用 JRE 6 并给了我错误的方法名称。
    如果我写 ste[2 + depth].getMethodName(). 就可以了

    • 0getStackTrace()
    • 1getMethodName(int depth)
    • 2 正在调用方法。

    virgo47answer(已投票)实际上计算了要应用的正确索引以获取方法名称。

    【讨论】:

    • 它只对我说“主要”。 :-/
    • @Amigable:您是否尝试打印所有 StackTraceElement 数组以进行调试并查看“main”是否真的是正确的方法?
    • 我使用 JRE 6 并给了我不正确的方法名称。如果我写ste[2 + depth].getMethodName(),它会起作用。 0 是getStackTrace(),1 是getMethodName(int depth),2 是调用方法。另见@virgo47's answer
    • @bluish:好点。我已将您的评论和对 virgo47 答案的引用包含在我的文章中。
    • @VonC 这个实现真的正确吗?此处的深度必须为 ste.length + 1 才能给出当前方法。如果我们要允许 depth = 0 ,它不应该是 ste[depth + 1] 吗?
    【解决方案4】:

    我们使用此代码来减轻堆栈跟踪索引的潜在可变性 - 现在只需调用 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 不会做得那么糟糕。 :-)

    【讨论】:

    • 这仍然微妙地依赖于供应商。 JVM 不需要为此代码提供可靠的数据。
    • 根据 JVM 规范,JVM 不需要提供完整的堆栈跟踪(优化、内联和所有这些),并且您已经发现您的启发式在 Oracle Java 5 和 Oracle Java 6 之间发生了变化。并不能保证任何其他 JVM 在代码中的行为都符合您的预期,因此您巧妙地依赖于供应商特定的行为。这很好,只要您知道这一点,但如果 - 例如 - 您需要部署在 IBM JVM(我们必须这样做)或 Zing 实例上,您可能需要重新审视您的启发式方法。
    • 这似乎是此处提供的所有选项中最强大的,尽管存在依赖关系。
    【解决方案5】:
     public class SomeClass {
       public void foo(){
          class Local {};
          String name = Local.class.getEnclosingMethod().getName();
       }
     }
    

    name 的值为 foo。

    【讨论】:

    • Local.class.getEnclosureMethod() 为空。 jdk1.6.0_31,玩1.2.5
    • @eigil 这很有趣,但如果没有更多信息,很难判断出了什么“错误”或者我们应该在什么时候期待null
    • 这和this answer是一样的。它的优点是它不会创建一个虚假的对象实例,它的缺点是它需要一个不能在语句中内联的类声明(即通常它需要额外的代码行)。
    • @eigil 您是在类(例如 SomeClass)还是在方法(例如 foo)中定义类?我发现定义子类而不包含在方法或构造函数中会导致 getEnclosureMethod() 返回 null。
    • 很确定我完全按照这个答案中的描述做了。我认为playframework有点奇怪。在“普通”java 中测试没有任何问题。
    【解决方案6】:

    这两个选项都适用于 Java:

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

    或者:

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

    【讨论】:

    • 对于静态方法使用:.class.getEnclosureMethod().getName()
    • 根据 Bombe 的回答和 javadoc 指示注意空数组。某些 JVM 可能没有填满 stacktrace 数组?
    【解决方案7】:

    最快的方法我发现是:

    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 depth)。并将可访问的 Method 存储在静态变量中。

    【讨论】:

    • 在性能方面最快?是否有任何微基准来支持该主张?
    • +1。在 1.6 上使用简单的定时循环,使用此方法进行 1,000,000 次迭代耗时 1219ms,而使用 new Throwable().getStackTrace() 耗时 5614ms。
    • m.setAccessible(true);应该被 AccessController.doPrivileged 包围。需要考虑的事情,我会说不是硬性规定
    • 在 2016 年测试,这仍然是最快的。像@ach 一样,我使用了 1M 次迭代。 1.7_79:1.6 秒对 15.2 秒 1.8_74:1.8 秒对 16.0 秒。 FWIW 我的基准 ste 数组的长度==23,但无论堆栈深度如何,此方法都保持快速。
    【解决方案8】:

    使用以下代码:

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

    【讨论】:

    • 这会为我打印出“getStackTrace” - 我使用的是 Java 1.5
    • 根据 Bombe 的回答和 javadoc 指示注意空数组。某些 JVM 可能没有填满 stacktrace 数组?
    【解决方案9】:

    这可以从 Java 9 开始使用 StackWalker 来完成。

    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 更高效,后者急切地为整个调用堆栈创建一个数组。 Also see the JEP for more information.

    【讨论】:

      【解决方案10】:
      public static String getCurrentMethodName() {
              return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
          }
      

      【讨论】:

      • 是的,目前为止最好的......把它变成一个方法并在跟踪中获取第三个 ([2]) 帧(或任何它的名称)。
      【解决方案11】:

      这是virgo47's answer(上图)的扩展。

      它提供了一些静态方法来获取当前和调用的类/方法名。

      /* Utility class: Getting the name of the current executing method 
       * https://stackoverflow.com/questions/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. https://stackoverflow.com/questions/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 + ")";
          }
      }
      

      【讨论】:

      • 这与@mklemenz 的回答相结合是访问堆栈信息的一种非常快速和干净的方式。
      【解决方案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。
      • 适用于安卓的是Thread.currentThread().getStackTrace()[2]
      【解决方案13】:

      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() 返回方法名。
      • getStackTrace()[2] 是错误的,它必须是getStackTrace()[3] 因为: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [ 3]调用这个的函数a()
      【解决方案14】:

      另一种方法是创建但不抛出异常,并使用该对象从中获取堆栈跟踪数据,因为封闭方法通常位于索引 0 - 只要 JVM 存储该信息,正如其他人在上面提到的那样。然而,这并不是最便宜的方法。

      来自Throwable.getStackTrace()(至少从 Java 5 开始就是这样):

      数组的第零个元素(假设数组的长度不为零)代表栈顶,也就是序列中的最后一个方法调用。 通常,这是创建和抛出此可抛物的点。

      下面的 sn-p 假设类是非静态的(因为 getClass()),但这是一个旁白。

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

      【讨论】:

        【解决方案15】:
        String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println("methodName = " + methodName);
        

        【讨论】:

        • 查看上面 mvanle virgo47 的答案和 thorbjorn-ravn-andersen 的评论。重复、不准确和不可靠的代码。
        • @ShivaKomuravelly 是的,但似乎在任何情况下都没有,所以我也是 -1。
        【解决方案16】:

        我有使用这个的解决方案(在 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())}));
            }
        }
        

        【讨论】:

          【解决方案17】:

          我不知道获取当前执行的方法名称的目的是什么,但如果这只是为了调试目的,那么像“logback”这样的日志记录框架可以在这里提供帮助。例如,在 logback 中,您需要做的就是use the pattern "%M" in your logging configuration。但是,应谨慎使用,因为这可能会降低性能。

          【讨论】:

            【解决方案18】:

            万一你想知道名字的方法是junit测试方法,那么你可以使用junit TestName规则:https://stackoverflow.com/a/1426730/3076107

            【讨论】:

            • @AndreiKonstantinov 我不认为这只是链接。即使您删除了链接,至少还有一些信息可以继续。
            【解决方案19】:

            我改写了一点maklemenz's answer:

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

            【讨论】:

              【解决方案20】:

              这里的大多数答案似乎都是错误的。

                  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
              

              【讨论】:

              • 您能否澄清为什么大多数答案对您来说似乎是错误的?有很多答案,我对 Java 的了解并不多,无法阅读所有答案并理解它们与您的答案之间的区别。 :(
              • @mmm 抱歉,我强烈反对。我来这里是为了学习,我相信许多其他人也是如此。我只是不明白为什么你认为我不应该在这个问题上了解更多。我想在我的代码中少犯错误并警告其他人,而不是遵循一些货物崇拜。您至少可以澄清这段代码在哪个 Java 版本上应该是正确的。 :( 下面的答案说堆栈跟踪在 1.5 和 1.6 之间发生了变化。也许你暗示在即将到来的 Java 14 中有类似的东西,我怎么知道。或者不同的供应商可能有。对不起,如果我把你的回答误解为粗鲁一。
              【解决方案21】:

              我将此代码 sn-p 与带有最新 Java 更新的最新 Android Studio 一起使用。可以从任何Activity、Fragment等中调用。

              public static void logPoint() {
                  String[] splitPath = Thread.currentThread().getStackTrace()[3]
                      .toString().split("\\.");
              
                  Log.d("my-log", MessageFormat.format("{0} {1}.{2}",
                      splitPath[splitPath.length - 3],
                      splitPath[splitPath.length - 2],
                      splitPath[splitPath.length - 1]
                  ));
              }
              

              这样称呼

              logPoint();
              

              输出

              ... D/my-log: MainActivity onCreate[(MainActivity.java:44)]
              

              【讨论】:

                【解决方案22】:
                MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
                

                【讨论】:

                • 请编辑更多信息。不建议使用纯代码和“试试这个”的答案,因为它们不包含可搜索的内容,也没有解释为什么有人应该“试试这个”。
                • 虽然此代码可能有助于解决问题,但它并没有解释为什么和/或如何回答问题。提供这种额外的背景将显着提高其长期教育价值。请edit您的答案添加解释,包括适用的限制和假设。
                • 仅适用于 Java 7+,但获取方法名称的简洁方式。尽管如此,仍然是此类调用的性能考虑因素。
                • getEnclosingMethod() 在 Java 7 中为我抛出 NullPointerException
                • java.lang.Class.getEnclosureMethod() 返回一个 Method 对象,表示底层类的直接封闭方法,如果此 Class 对象表示方法中的本地或匿名类,否则返回 null。
                【解决方案23】:

                这种方法有什么问题:

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

                【讨论】:

                • @Saksham 在我看来,这实际上是试图回答这个问题。不是一次伟大的尝试,但仍然是一次尝试。
                • @ivarni “不是一个好的尝试”?它出什么问题了?你熟悉“接吻原则”吗?
                • @johnny 在我面前的代码库中,现在有 271 个类。即使每个类(低估计)og 5 方法也超过 1300 种方法。这甚至不是一个大的代码库。您没有看到扩大方法的问题吗?我很高兴同意不同意,但这就是为什么我说这不是一个好的尝试。它会在任何重要的代码库中引入大量开销。
                • @ivarni 您是否必须在每个方法中都包含一个方法调用(如上所述)才能执行相同且不太可靠的功能?
                • @johnny 我想我已经看到太多的情况,方法名称与调试时向错误方向发送的字符串不匹配。但是在 Java 中,我仍然认为您的建议是最好的,其他替代方案“成本”太高了。
                猜你喜欢
                • 1970-01-01
                • 2023-03-10
                • 2016-03-13
                • 2011-01-04
                • 2018-06-18
                • 2010-09-19
                • 2016-11-01
                • 2013-06-18
                • 1970-01-01
                相关资源
                最近更新 更多