基本上我在方法中有一个日志语句。每当调用该方法时,我都希望轻松调用该方法的名称,并将其附加到logging语句中。这样做是为了最小化我的应用程序中的硬编码行数。这可能便宜吗?
答案 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
在一两个星期之前就像上面的日志一样敲打我的头(方法名称是硬编码的)。没有感觉它比没有记录更有帮助。