Java 为什么我们将 Loggers 声明为 static final?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6653520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 12:23:53  来源:igfitidea点击:

Why do we declare Loggers static final?

javalogging

提问by user489041

In Java, why is it best practice to declare a logger static final?

在 Java 中,为什么声明记录器是最佳实践static final

private static final Logger S_LOGGER

采纳答案by Tomasz Nurkiewicz

  • private- so that no other class can hiHymanyour logger
  • static- so there is only one logger instance per class, also avoiding attempts to serialize loggers
  • final- no need to change the logger over the lifetime of the class
  • private- 这样其他班级就不能劫持您的记录器
  • static- 所以每个类只有一个记录器实例,也避免了尝试序列化记录器
  • final- 无需在类的整个生命周期内更改记录器

Also, I prefer name logto be as simple as possible, yet descriptive.

此外,我更喜欢名称log尽可能简单,但具有描述性。

EDIT: However there is an interesting exception to these rules:

编辑:但是,这些规则有一个有趣的例外:

protected final Logger log = LoggerFactory.getLogger(getClass());

as opposed to:

与:

private static final Logger log = LoggerFactory.getLogger(Foo.class);

The former way allows you to use the same logger name (name of the actual class) in all classes throughout the inheritance hierarchy. So if Barextends Foo, both will log to Barlogger. Some find it more intuitive.

前一种方式允许您在整个继承层次结构中的所有类中使用相同的记录器名称(实际类的名称)。因此,如果Barextends Foo,两者都将记录到Bar记录器。有些人觉得它更直观。

回答by Jon Skeet

When would you want to change the value of the field?

您希望何时更改该字段的值?

If you're never going to change the value, making the field final makes it obviousthat you'll never change the value.

如果您永远不会更改该值,那么将字段设为 final 就很明显您永远不会更改该值。

回答by Vincent Mimoun-Prat

Because that is usually the kind of functionnality that can be shared accross all instances of your objects. It does not make much sense (90% of the time) to have a different logger for two instances of the same class.

因为这通常是一种可以在对象的所有实例之间共享的功能。为同一类的两个实例使用不同的记录器并没有多大意义(90% 的时间)。

However, you can also see sometimes logger classes declared as singletons or even simply offering static functions to log your stuff.

但是,有时您也可以看到 logger 类被声明为单例,甚至只是提供静态函数来记录您的内容。

回答by Liv

Normally you initialize the logger to log using the class name -- which means that if they weren't static, you would end up with each instance of the class having an instance of it (high memory footprint), but all of these loggers would share the same configuration and behave exactly the same. That's the reason behind the staticbit. Also because each Loggeris initialised with the class name, to prevent conflicts with subclasses, you declare it privateso it cannot be inherited. The finalcomes from the point that you normally don't change the Loggerduring the execution -- so once initialized you never "re-configured" it -- in which case it makes sense to make it final to ensure no one can change it (by mistake or otherwise). Of course if you are going to use a Loggerin a different way you might need NOTto use static final-- but I would venture to guess 80% of apps would use logging as explained above.

通常,您使用类名初始化记录器以记录日志——这意味着如果它们不是静态的,那么最终类的每个实例都会有一个它的实例(高内存占用),但所有这些记录器都会共享相同的配置并且行为完全相同。这就是static位背后的原因。也因为每个Logger都用类名初始化,为了防止与子类发生冲突,你声明它private不能被继承。这final来自于您通常不会Logger在执行期间更改的点- 所以一旦初始化,您就永远不会“重新配置”它 - 在这种情况下,将其设为最终以确保没有人可以更改它是有意义的(通过错误或其他)。当然,如果您要使用Logger以不同的方式,您可能需要来使用static final-但我冒昧猜测应用程序的80%的人会使用日志记录如上所述。

回答by Andrzej Doyle

staticmeans that you only create one Logger per class, not one logger per instanceof your class. Generally, this is what you want - as the loggers tend to vary solely based on class.

static意味着您只为每个类创建一个 Logger,而不是为您的类的每个实例创建一个记录器。通常,这就是您想要的 - 因为记录器往往会因类而异。

finalmeans that you're not going to change the value of the loggervariable. Which is true, since you almost always throw all log messages (from one class) to the same logger. Even on the rare occasions where a class might want to send some messages to a different logger, it would be much clearer to create another logger variable (e.g. widgetDetailLogger) rather than by mutating the value of a static variable on the fly.

final意味着你不会改变logger变量的值。这是真的,因为您几乎总是将所有日志消息(来自一个类)扔到同一个记录器。即使在一个类可能想要将一些消息发送到不同的记录器的极少数情况下,创建另一个记录器变量(例如widgetDetailLogger)而不是通过动态改变静态变量的值会更清晰。

回答by zacheusz

In most cases, you are not going to change the reference and finalmodifier marks it. You don't need separate instances for each class instance - so static. And first of all this is for performance- it can be nicely optimized (final) and saves memory (static).

在大多数情况下,您不会更改引用和final修饰符标记它。您不需要为每个类实例使用单独的实例 - 所以static. 和第一这一切是性能-它可以很好地优化(最终)和节省内存(静态)。

回答by Daniel Leschkowski

To answer that question, you should have asked yourself what "static" and "final" are for.

要回答这个问题,您应该问自己“静态”和“最终”是什么。

For a Logger, (I assume you talk about Log4J Logger class) you want a category per class. Which should lead to the fact that you assign it only once, and there is no need for more than one instance per class. And presumably there is no reason to expose the Logger object of one class to another, so why dont make it private and follow some OO-Principles.

对于 Logger,(我假设您谈论的是 Log4J Logger 类)您希望每个类都有一个类别。这应该导致您只分配一次,并且每个类不需要多个实例。并且大概没有理由将一个类的 Logger 对象暴露给另一个类,那么为什么不将其设为私有并遵循一些 OO 原则。

Also you should note, that the compiler is able to take benefits of that. So your code performs a bit better :)

您还应该注意,编译器能够从中受益。所以你的代码性能好一点:)

回答by yegor256

Check this blog post: Get Rid of Java Static Loggers. This is how you use slf4j with jcabi-log:

查看这篇博文:摆脱 Java 静态记录器。这是将 slf4j 与jcabi-log一起使用的方式:

import com.jcabi.log.Logger;
class Foo {
  void save(File f) {
    Logger.info(this, "file %s saved successfully", f);
  }
}

And never use that static noise any more.

永远不要再使用这种静态噪音。

回答by Paul

In addition to the reasons given in the other answers one thing I ran into was that if my logger was neither static nor final:

除了其他答案中给出的原因之外,我遇到的一件事是,如果我的记录器既不是静态的也不是最终的:

...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);

public String toJson() {
  GsonBuilder gsonBuilder = new GsonBuilder();   
  return gsonBuilder.create().toJsonTree(this).toString();
}
...

in certain cases (when I was using the Gson library) I would get stackoverflow exception. My specific situation was to instantiate the class containing the non static non final logger. Then call the toJson method which invoked GsonBuilder:

在某些情况下(当我使用 Gson 库时)我会得到 stackoverflow 异常。我的具体情况是实例化包含非静态非最终记录器的类。然后调用调用 GsonBuilder 的 toJson 方法:

...
DataSummary ds = new DataSummary(data);    
System.out.println(ds.toJson());
...

回答by nkduqi

This code is vulnerable,but, after Java7, we can use Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); instead of static logger.

这段代码是有漏洞的,但是在Java7之后,我们可以使用Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); 代替静态记录器。