Div*_*ero 11 java reflection logging
我有一个日志功能,它将调用对象作为参数.然后我调用getClass().getSimpleName(),以便我可以轻松获取要添加到我的日志条目的类名,以便于参考.问题是,当我从静态方法调用我的日志函数时,我无法传入"this".我的日志功能看起来像这样:
public static void log(Object o, String msg){
do_log(o.getClass().getSimpleName()+" "+msg);
}
public void do_something(){
log(this, "Some message");
}
Run Code Online (Sandbox Code Playgroud)
但是,假设我想从静态函数登录:
public static void do_something_static(){
log(this, "Some message from static");
}
Run Code Online (Sandbox Code Playgroud)
显然do_something_static()不起作用,因为它是静态的,而"this"不在静态上下文中.我怎么能绕过这个?我是否可以在不使用反射的情况下完成它(因为我知道有很多开销涉及并且它可能会影响性能,因为我记录了很多数据)
我知道我可能会以某种方式将当前类硬编码到调用中,但我确信当我将函数移动到另一个类时,我将忘记更新硬编码引用,它将不再正确.
谢谢!
Osc*_*Ryz 14
您可以添加"Class"作为第一个参数并重载日志方法:
public class SomeClass {
// Usage test:
public static void main( String [] args ) {
log( SomeClass.class, "Hola" );
log( new java.util.Date(), "Hola" );
}
// Object version would call Class method...
public static void log( Object o , String msg ) {
log( o.getClass(), msg );
}
public static void log( Class c , String message ) {
System.out.println( c.getSimpleName() + " " + message );
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
$ java SomeClass
SomeClass Hola
Date Hola
Run Code Online (Sandbox Code Playgroud)
但是将调用类作为第一个参数传递感觉真的很糟糕.这里面向对象模型与"程序"风格相反.
您可以使用堆栈跟踪获取调用类,但正如您所提到的,如果您将其调用数千次,则会产生开销.
但是如果你创建的是类变量,那么如果你碰巧有1000个类使用这个实用程序,那么只有一个实例,你最多可以有1000个调用.
这样的事情会更好(另一个答案的微妙变化):
public class LogUtility {
private final String loggingFrom;
public static LogUtility getLogger() {
StackTraceElement [] s = new RuntimeException().getStackTrace();
return new LogUtility( s[1].getClassName() );
}
private LogUtility( String loggingClassName ) {
this.loggingFrom = "("+loggingClassName+") ";
}
public void log( String message ) {
System.out.println( loggingFrom + message );
}
}
Run Code Online (Sandbox Code Playgroud)
使用测试:
class UsageClass {
private static final LogUtility logger = LogUtility.getLogger();
public static void main( String [] args ) {
UsageClass usageClass = new UsageClass();
usageClass.methodOne();
usageClass.methodTwo();
usageClass.methodThree();
}
private void methodOne() {
logger.log("One");
}
private void methodTwo() {
logger.log("Two");
}
private void methodThree() {
logger.log("Three");
}
}
Run Code Online (Sandbox Code Playgroud)
产量
$ java UsageClass
(UsageClass) One
(UsageClass) Two
(UsageClass) Three
Run Code Online (Sandbox Code Playgroud)
注意声明:
....
class UsageClass {
// This is invoked only once. When the class is first loaded.
private static final LogUtility logger = LogUtility.getLogger();
....
Run Code Online (Sandbox Code Playgroud)
这样,如果你使用来自objectA,objectB,objectC的"logger"或类方法(如main)它们都将拥有一个记录器实例并不重要.
查询堆栈跟踪可能对您的问题很不利.你有3种可能的方法.
只需创建一个异常实例并获取第一帧:
static String className() {
return new RuntimeException().getStackTrace()[0].getClassName();
}
Run Code Online (Sandbox Code Playgroud)
使用Thread更加容易:
static String className2() {
return Thread.currentThread().getStackTrace()[1].getClassName();
}
Run Code Online (Sandbox Code Playgroud)
这两种方法的缺点是你不能重复使用它们.所以你可能想为它定义一个Helper类:
class Helper {
public static String getClassName() {
return Thread.currentThread().getStackTrace()[2].getClassName();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以通过编程方式获取类名,而无需对类名进行硬编码:
public static void log(Object o, String msg){
do_log(Helper.getCClassName() + " " + msg);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
35761 次 |
| 最近记录: |