2011-07-14 29 views
9

基本上我有一个方法内的日志语句。每当调用该方法时,我都想轻松调用该方法的名称,并将其附加到日志记录语句中。这样做是为了尽量减少我的应用程序中硬编码行的数量。这可能做到便宜吗?我可以便宜地调用Java方法来获取当前方法的名称吗?

+1

我不认为有一个很好的方法可以在运行时使用,但是您可能可以注释需要此功能的方法,然后编写一个注释处理器,并将其纳入您的构建过程。在运行时,它几乎与硬编码方法的名称一样工作,但实际上并不需要硬编码任何东西。 –

+0

[获取当前执行方法的名称]的可能重复(http://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method) – bmargulies

回答

15

不,不便宜。执行此操作的昂贵和唯一方法是使用StackTrace方法调用。最好只是硬编码。

+0

嗯,那太糟糕了。不知道为什么java不能很便宜地做到这一点。 –

+0

AspectJ的目的是为了处理这样的问题 – antlersoft

+0

我将如何使用AspectJ做这样的事情?我能找到的最接近的方法是“getSourceMethod()” –

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

+0

'String test(int i){0} { StackTraceElement ste = Thread.currentThread()。getStackTrace()[i]; // String aString =“bleh”; //返回aString; return ste。getMethodName(); }} ' 我跑的测试做一个硬编码和做堆栈跟踪之间//使用堆栈跟踪 //30.281秒 //33024.00845414616呼叫/秒 //第二次运行 //17.937秒 // 55750个呼叫/秒 //随着硬串 //0.016秒 //6.25E7呼叫/秒---基本上一个substantialy 100倍增加成本相比于硬编码的字符串返回 – TravMan

+0

右。但这一切都取决于调用此代码的频率。假如你每秒只打一次电话,也许你可以负担得起。 –

+0

对于简单地记录当前方法名称的注释或其他内容,我可以在不更改愚蠢的字符串的情况下剪贴粘贴事物? – ggb667

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>" 
+0

这使用StackTrace,并要求您使用Java记录器。如果你在家中的一个小应用中进行测试,那很好,但按照StackTrace下面的测试运行速度要慢100倍。 – TravMan

+0

@TravMan我同意,他只是要求一个外部方法,他可以调用这将返回调用方法的名称,除非硬编码名称(显然[和[wooo坏]反射),这种方法将是最快的。然而,100次没有参考框架,我想这完全没有实际意义,我们正在追逐微型优化童话。 – Andrew

+0

也upvoted,从来没有使用过这样的Logger类 – TravMan

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 

被敲我的日志上像头只在一两个星期前上述(方法的名字被硬编码)。没有感觉到它明显比没有日志记录更有帮助。

相关问题