此答案的评论How do you reduce Java logging boilerplate code?强烈建议不要使用记录器作为实例成员变量。我可以想到两个负面的副作用:
1)超类日志与子类的记录器
2)对象无法序列化(除非标记为瞬态)
但是如果不需要序列化并且使用子类名称进行日志记录不是问题,那还有什么可以避免的原因吗?我认为它减少了样板代码,避免了将logger变量定义从一个类复制到另一个类时的复制粘贴错误。甚至Spring框架(我认为它具有非常好的编码标准)也使用这种方法。
答案 0 :(得分:9)
如果您的Logger是实例成员而不是静态成员,则每次创建新对象时都必须检索Logger。尽管这种开销可能微不足道,但这是一个缺点。
从设计角度来看,Loggers实际上并不是对象的属性,因为它们通常是关于系统的元信息,而不是系统本身的业务信息。与Logger
或Car
相同的方式,Engine
实际上不属于Transmission
对象。将记录器绑定到对象作为成员(在大多数情况下)在语义上没有任何意义。
答案 1 :(得分:3)
您可能希望查看讨论该主题的这些页面:
答案 2 :(得分:2)
除了子类名称的Superclass日志记录之外的主要区别在于,每个类的成员都有一个Logger
对象。根据使用日志记录的类数量,这可能是大量的Logger,因此内存膨胀可能是一个问题。
从抽象的角度来看,记录器确实属于该类,并且可以在所有实例之间共享,而不是每个实例都需要自己的私有副本,因此将其声明为静态是有意义的。翻转你的问题,它有什么优势使其非静态? (能够将getClass()
传递给getLogger()
调用而不是传递类常量是我唯一能想到的,这是一件很小的事情。)
答案 3 :(得分:1)
另一个,可能是次要内容:浪费内存,特别是当你有很多实例时,每个实例都有自己的记录器
答案 4 :(得分:0)
尝试调试错误,当SuperClass
类中确实记录错误时,您会看到SubClass
类生成的消息。我已经看到了几种情况,开发人员创建了一个LoggingUtils
类,它生成的消息通常会复制已经由日志记录框架烘焙的内容。
我看到使用共享日志记录实例的唯一真实情况类似于Apache commons HttpClient logger httpclient.wire
,它在几个类之间共享,用于记录通过客户端发送的请求和响应的内容。这种特殊的日志记录情况不记录包的实际实现信息,它记录有关整个http“事务”的信息。
答案 5 :(得分:0)
其中一个主要问题是清理内存实例。即使您不创建类的对象,因为您使用logger的静态实例,将会引用这些对象。
同样如apache所说,这会保留引用,因此在使用后它们不会被释放一次。
在某些情况下,使用静态限定符可能是有益的。然而在其他情况下,这确实是一个非常糟糕的主意,并且会产生意想不到的后果。
使用static的技术结果很明显:在类的所有实例中只共享一个Log引用。这显然是记忆效率高的;无论创建多少个实例,只需要一个引用(4或8个字节)。它还具有CPU效率;在首次引用类时,查找Log实例所需的查找只执行一次。