Answers:
private
-这样其他任何人都无法劫持您的记录器static
-因此每个类只有一个记录器实例,也避免了尝试对记录器进行序列化final
-无需在课堂上更改记录器另外,我更喜欢名字 log
尽可能简单,但具有描述性。
编辑:但是这些规则有一个有趣的例外:
protected final Logger log = LoggerFactory.getLogger(getClass());
相对于:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
前一种方法允许您在整个继承层次结构的所有类中使用相同的记录器名称(实际类的名称)。因此,如果Bar
extends Foo
,两者都将记录到Bar
记录器。有些人觉得它更直观。
log
名字,而不喜欢用分散代码LOG
。只是开发人员的问题。团队协议。
检查此博客文章:摆脱Java Static Loggers。这是将slf4j与jcabi-log结合使用的方式:
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
再也不要使用该静态噪声了。
static
意味着每个类仅创建一个Logger,而不是每个类实例创建一个Logger 。通常,这就是您想要的-因为记录器往往仅根据类而有所不同。
final
表示您不会更改logger
变量的值。的确如此,因为您几乎总是将所有日志消息(来自一个类)扔给同一记录器。即使在极少数的情况下,一个类可能希望向其他记录器发送一些消息,创建另一个记录器变量(例如widgetDetailLogger
)也比通过动态更改静态变量的值更加清晰。
您何时想更改该字段的值?
如果你永远也不会改变的值,使得现场最终使其明显,你永远不会改变的价值。
通常,您将记录器初始化为使用类名进行记录-这意味着,如果它们不是静态的,则最终会导致该类的每个实例都有一个实例(占用大量内存),但是所有这些记录器都会共享相同的配置,并且行为完全相同。这就是背后的原因static
。另外,由于每个Logger
类都使用类名进行了初始化,因此为了避免与子类发生冲突,请对其进行声明,private
以使其无法继承。在final
出现这种情况,是因为您通常Logger
在执行过程中不会更改-因此,一旦初始化就永远不会“重新配置”它-在这种情况下,有必要将其确定为最终确定以确保没有人可以更改它(通过错误或其他)。当然,如果您要使用Logger
以不同的方式,您可能需要不来使用static final
-但我冒昧猜测应用程序的80%的人会使用日志记录如上所述。
要回答这个问题,您应该问自己“静态”和“最终”是什么意思。
对于Logger(我假设您谈论Log4J Logger类),您希望每个类都有一个类别。这应该导致这样的事实,您只分配一次,并且每个类不需要多个实例。并且大概没有理由将一类的Logger对象公开给另一类,因此为什么不将其设为私有并遵循某些OO原理。
您还应该注意,编译器可以利用这一点。因此您的代码执行起来会更好:)
因为通常这是可以在对象的所有实例之间共享的一种功能。对于同一个类的两个实例,使用不同的记录器是没有任何意义的(90%的时间)。
但是,有时您还会看到记录器类声明为单例,甚至只是提供静态函数来记录您的内容。
该代码容易受到攻击,但是,在Java7之后,我们可以使用它Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
代替静态记录器。
This is code is vulnerable
您能否澄清一下答案?
理想情况下,直到Java 7为止,Logger都应遵循以下规定,以便不给出Sonar并给出合规代码:private:永远不能在其父类之外访问。如果另一个类需要记录某些内容,则应实例化其自己的记录器。静态:不依赖于类(对象)的实例。在记录某些内容时,当然可以在消息中提供上下文信息,但是应该在类级别创建记录器,以防止与每个对象一起创建记录器,从而防止占用大量内存。final:每个班级只能创建一次。
除了其他答案中给出的原因外,我遇到的一件事是,如果我的记录器既不是静态的也不是最终的:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
在某些情况下(当我使用Gson库时),我会得到stackoverflow异常。我的具体情况是实例化包含非静态非最终记录器的类。然后调用调用GsonBuilder的toJson方法:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
实际上,静态记录器可能“有害”,因为它们应该在静态上下文中工作。当具有动态环境时 OSGi可能有助于使用非静态记录器。由于某些日志记录实现会在内部缓存日志记录器(AFAIK至少为log4j),因此对性能的影响可以忽略不计。
静态记录器的一个缺点是例如。垃圾回收(当一个类仅使用一次时,例如,在初始化期间,记录器仍会保留)。
有关更多详细信息,请检查:
也可以看看:
根据我从Internet上获得的有关使记录器静态或不静态的信息,最佳实践是根据用例使用它。
有两个主要参数:
1)当您将其设为静态时,它不会被垃圾回收(内存使用和性能)。
2)当您不使其静态时,将为每个类实例创建一个(内存用法)
因此,当您为单例创建记录器时,无需使其静态。因为只有一个实例,所以只有一个记录器。
另一方面,如果要为模型或实体类创建记录器,则应使其不创建重复的记录器为静态。