我正在尝试提高Java的优化技能。为了实现这一目标,我制作了一个旧程序,并且我正在尽力使其变得更好。在这个程序中,我使用SL4J进行日志记录。为了得到记录器我做了:
private static final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
在我编写代码的时候,我认为这是最好的选择,因为我删除了对类名的引用(可能会被重构)。但现在我不再那么肯定了......
private static final Logger logger = LoggerFactory.getLogger(ClassName.class);
另一方面,保留对类名的引用,但它会删除一个方法调用。对于一个班级来说,这可能不是一个很大的改进,但是当你有很多班级时,这可能就是一个问题。
所以我的问题是:
哪种方法更好?使用类名还是通过反射获取?
请用赞成和反对来激励你的答案。谢谢。
答案 0 :(得分:10)
我会在这里分享我的观点。我会说这是你不应该从性能的角度来打扰的情况。可能在代码中有一些部分可以比这个更好地进行优化:)
现在,关于你的问题。查看LoggerFactory's代码
请注意,extract[Condition]
只调用重载方法:
getLogger(Class<?> name)
并进行一些额外的计算。所以使用String的方法显然要快一些。
通常,模式是将Logger引用保持为类中的静态字段,如下所示:
Logger logger = getLogger(clazz.getName());
在这种情况下,您无法真正使用public class SomeClass {
private static final Logger LOG = LoggerFactory.getLogger(SomeClass.class);
}
,因为this.getClass()
实际上并不存在(您在静态环境中运行)。
根据我的经验,最好使用this
作为参数,除非您真的想要使用来自不同类的相同记录器。在这种情况下,您最好使用一些表示记录器的逻辑常量。
例如,我们假设您尝试使用3个不同的类来访问数据库。 因此,您创建了logger&#39; DB&#39;,分配一个将写入database.log的文件追加器,并且您希望在这3个不同的类中重用相同的记录器。
所以你应该使用以下代码:
ClassName.getClass()
希望这有帮助
答案 1 :(得分:6)
我通常做的是
private static final Logger logger = LoggerFactory.getLogger(ClassName.class);
然而,成语
protected final Logger log = LoggerFactory.getLogger(getClass());
同样很常见。 In this question您可以找到有关这些约定的更多信息。
答案 2 :(得分:5)
我更喜欢
/**
* Expensive function
* @param {string} lists
* @returns {object}
*/
function expensiveFunction(lists){
angular.forEach(lists, function (key, value) {
lists.display = true; // here goes your logic
});
return lists;
}
var myList = expensiveFunction(myList);
<ul>
<li ng-show="a.dispaly" ng-repeat="a in myList">
<a ng-click="onMove(period)">Move here </a>
</li>
<li ng-hide="!canBook">
<small>No free resources</small>
</li>
</ul>
因为
Logger logger = LoggerFactory.getLogger(ClassName.class);
可以由其中一个类子项覆盖,您将在日志中看到子类名。有时它可能会令人困惑,因为日志实际上是在父类中执行的
答案 3 :(得分:3)
最新条目!
因为我将来可能会搜索这个。
有一种方法可以通过使用Java 7的MethodHandles类来创建对复制/粘贴友好的Logger实例(这几乎绝对不是做某事的好理由!)。
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
答案 4 :(得分:0)
如果您在每次声明记录器时都不想编写类名,可以使用以下实用程序方法:
public static org.slf4j.Logger getLogger() {
final Throwable t = new Throwable();
t.fillInStackTrace();
return LoggerFactory.getLogger(t.getStackTrace()[1].getClassName());
}
该方法可以使用:
private static final Logger LOG = TheClassContainingTheMethod.getLogger();
使用这种方法,记录器声明对于所有类始终是相同的。
答案 5 :(得分:0)
在静态环境中,您不能使用LoggerFactory.getLogger(getClass())
或LoggerFactory.getLogger(this.getClass().getName())
然后您必须使用LoggerFactory.getLogger(ClassName.class)
无论如何,我更喜欢Lombok的@Log4j2
,更少的代码就能完成工作:https://projectlombok.org/api/lombok/extern/log4j/Log4j2.html
答案 6 :(得分:-2)
我用这个
private static final Logger log = LoggerFactory.getLogger(ClassName.class);
答案 7 :(得分:-2)
使用此
private final Logger logger = LoggerFactory.getLogger(this.getClass());
}
// logic
try
{
// todo
}
catch (NullPointerException e) {
logger.error("Error:-" + e.getMessage());
return ResponseUtil.errorResponse(e.getMessage());
}
catch (Exception e) {
logger.error("Error:-" + e.getMessage());
return ResponseUtil.errorResponse(e.getMessage());
}