我可以廉价地调用Java方法来获取当前方法的名称吗?

时间:2011-07-14 19:39:18

标签: java

基本上我在方法中有一个日志语句。每当调用该方法时,我都希望轻松调用该方法的名称,并将其附加到logging语句中。这样做是为了最小化我的应用程序中的硬编码行数。这可能便宜吗?

4 个答案:

答案 0 :(得分:15)

不,不便宜。这种昂贵且唯一的方法是使用StackTrace方法调用。最好只是硬编码。

答案 1 :(得分:3)

如果您只需要方法名称和行号,则可以合理快速地完成。在我的微基准测试中,您每秒可以进行大约120000次呼叫:

public class A {
  private static final int N = 1000000;

  public static void main(String[] args) {
    A a = new A();
    long l = System.currentTimeMillis();
    for (int i = 0; i < N; i++) {
      a.test(0);
      a.test(1);
      a.test(2);
    }
    double time = (System.currentTimeMillis() - l) / 1000d;
    System.err.println(time + " seconds");
    System.err.println(N / time + " calls/second");
  }

  String test(int i) {
    StackTraceElement ste = Thread.currentThread().getStackTrace()[i];
    return ste.getMethodName() + ":" + ste.getLineNumber();
  }
}

另见this answer

答案 2 :(得分:2)

为什么重新发明轮子,java.util.logging.Logger使用

 /**
* Gets the StackTraceElement of the first class that is not this class.
* That should be the initial caller of a logging method.
* @return caller of the initial logging method or null if unknown.
*/
private StackTraceElement getCallerStackFrame()
{
 Throwable t = new Throwable();
 StackTraceElement[] stackTrace = t.getStackTrace();
 int index = 0;

 // skip to stackentries until this class
 while(index < stackTrace.length
   && !stackTrace[index].getClassName().equals(getClass().getName()))
   index++;

 // skip the stackentries of this class
 while(index < stackTrace.length
   && stackTrace[index].getClassName().equals(getClass().getName()))
   index++;

  return index < stackTrace.length ? stackTrace[index] : null;
}

我怀疑你会比这更快得到它。

[编辑]要使用调用方法名称,

StackTraceElement caller = getCallerStackFrame();
String name = caller != null ? caller.getMethodName() : "<unknown>"

答案 3 :(得分:1)

您是否考虑过编写合理的日志消息?我的意思是,消息只告诉读者记录代码如何运行的“故事”?消息对于不同的方法确实不同?

  log4j: some.package.Class1: method1: checkpoint #1
  log4j: some.package.Class1: method1: checkpoint #2
  log4j: some.package.Class2: method2: checkpoint #1
  log4j: some.package.Class2: method2: checkpoint #2

在一两个星期之前就像上面的日志一样敲打我的头(方法名称是硬编码的)。没有感觉它比没有记录更有帮助。