回答
private
- 使其他类可以劫持您记录static
- 所以只有一个每个类的记录器实例,也避免试图序列记录器final
- 无需改变日志记录器
此外,我更喜欢名称log
尽可能简单,但描述性。
编辑:但是还有一个有趣的例外规则:
protected final Logger log = LoggerFactory.getLogger(getClass());
,而不是:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
前者的方法可以让你使用相同的记录器名称(实际名称类)遍历继承层次结构中的所有类。因此,如果Bar
延伸Foo
,则两者都将登录到Bar
记录器。有些人觉得更直观。
什么时候你想改变字段的值?
如果你永远不会改变这个值,那么使得这个字段最终成为明显的,你永远不会改变它的值。
在很多情况下,显然不添加final这个词,它就会变成一种垃圾。 – Dima
@Dima:那么我仍然感激编译器仍然会抛出一个错误,如果我*不小心尝试在这些情况下尝试更改值... –
因为这通常是可以在您的对象的所有实例中共享的那种功能。对于同一类的两个实例有不同的记录器没有太大意义(90%的时间)。
但是,你也可以看到声明为单身人士甚至干脆提供静态函数来记录你的东西,有时记录器类。
通常你初始化记录器使用类名进行登录 - 这意味着,如果他们不是一成不变的,你最终会具有它的一个实例(高内存占用)类的每个实例,但所有这些记录器将共享相同的配置并且行为完全相同。这就是static
位背后的原因。此外,因为每个Logger
被初始化与类名,以防止与子类冲突,声明它private
所以它不能被继承。 的final
来自于你不应该在执行过程中改变Logger
点 - 所以一旦初始化你永远不会“重新配置”它 - 在这种情况下,它是有道理的,使其最终确保无人可换它(通过错误或其他方式)。 当然,如果您打算以不同的方式使用Logger
,您可能需要而不是以使用static final
- 但我敢说大概猜测80%的应用程序会使用日志记录,如上所述。
static
意味着你只能创建每类中的一个记录器,每实例类的没有一个记录器。一般来说,这就是你想要的 - 因为伐木者往往只根据班级而变化。
final
表示您不打算更改logger
变量的值。这是真的,因为你几乎总是把所有的日志消息(从一个类)扔到同一个记录器。即使在极少数情况下,类可能想要将某些消息发送到不同的记录器,但创建另一个记录器变量(例如widgetDetailLogger
)会更清晰,而不是通过动态地变更静态变量的值。
在大多数情况下,您将要更改该值,final
修饰符会将其标记。对于每个类实例,您不需要单独的实例 - 因此static
。 首先这是为了性能 - 它可以很好地优化(最终)并保存内存(静态)。
要回答这个问题,你应该问自己什么是“静态”和“最终”。
对于Logger,(我假设你谈论Log4J Logger类),你需要每个类的类别。这应该导致只分配一次的事实,并且每个类不需要多个实例。大概没有理由将一个类的Logger对象暴露给另一个类,为什么不把它设为私有并遵循一些面向对象原则。
另外你应该注意,编译器能够从中受益。所以你的代码执行更好一点:)
检查此博文:Get Rid of 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);
}
}
而且从来没有使用静态噪声了。
一个有趣的选择,绝对清洁。我想知道这与个人班级记录员相比如何。 – Ross
每次写更长的记录器..(this,...)。罗。 –
除了其他答案一两件事,我跑进是给出的理由是,如果我的记录既不是静态的也不是最后:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
在某些情况下
(我用的是GSON库)我会得到stackoverflow异常。我的具体情况是实例化包含非静态非最终记录器的类。然后调用的toJSON方法,它调用GsonBuilder:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
此代码是脆弱的,但Java7后,我们就可以使用Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
,而不是静态的记录。
- 1. 为什么我们要声明一个静态方法
- 2. 为什么我们要在普通类中声明静态类?
- 3. 为什么变量应声明为静态和最终
- 4. 为什么不能在非静态块中声明静态最终变量?
- 5. 为什么我的登录方法声明为静态?
- 6. 为什么WebMethod声明为静态?
- 7. 声明不能被标记为“静态”,为什么
- 8. 为什么要声明对最终课程实例的引用是最终的?
- 9. 为什么静态变量需要在C++中声明两次
- 10. 应该将GSON声明为静态最终?
- 11. Checkstyle自定义规则确保记录器被声明为静态最终类属性
- 12. 为什么我不能转发声明静态函数?
- 13. PHP - 为什么我无法声明静态常量变量?
- 14. 为什么我要声明<PHP
- 15. 为什么我们需要的java.sql声明*包
- 16. 声明静态变量时的输出是什么?为什么?
- 17. 为什么声明的顺序对于静态初始化器很重要?
- 18. 即使函数是静态的,为什么我们不能在函数体内声明静态变量?
- 19. 我们为什么要在PHP中使用静态调用?
- 20. 为什么我要使用静态库?
- 21. 我们真的需要python中的@staticmethod装饰器声明静态方法
- 22. 为什么我们可以有静态最终成员,但不能在内部类中使用静态方法?
- 23. 应该记录器总是最终的和静态的?
- 24. 在公共最终静态记录器上禁用Checkstyle警告
- 25. 为什么要在C#中声明静态类为密封和抽象?
- 26. 为什么要求将全局匿名工会声明为静态?
- 27. 为什么.NET委托不能被声明为静态?
- 28. 为什么依赖属性被声明为静态只读?
- 29. 为什么只有静态字段可以声明为'const'?
- 30. 为什么jsp中的EL函数必须声明为静态?
+1,答案在修饰符中。 – mre
if static and final then LOG(大写) – zacheusz
* @ zacheusz *,我知道这就是要点。一些人虔诚地遵循Java命名约定(没有什么不妥),但我更愿意写和更愉快的阅读'log'名称,而不是用'LOG'分散代码。只是开发的问题。团队协议。 –