用于定义记录器非静态的缺点

时间:2009-01-14 17:09:14

标签: java logging

此答案的评论How do you reduce Java logging boilerplate code?强烈建议不要使用记录器作为实例成员变量。我可以想到两个负面的副作用:
1)超类日志与子类的记录器
2)对象无法序列化(除非标记为瞬态)

但是如果不需要序列化并且使用子类名称进行日志记录不是问题,那还有什么可以避免的原因吗?我认为它减少了样板代码,避免了将logger变量定义从一个类复制到另一个类时的复制粘贴错误。甚至Spring框架(我认为它具有非常好的编码标准)也使用这种方法。

6 个答案:

答案 0 :(得分:9)

如果您的Logger是实例成员而不是静态成员,则每次创建新对象时都必须检索Logger。尽管这种开销可能微不足道,但这是一个缺点。

从设计角度来看,Loggers实际上并不是对象的属性,因为它们通常是关于系统的元信息,而不是系统本身的业务信息。与LoggerCar相同的方式,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所说,这会保留引用,因此在使用后它们不会被释放一次。

Apache Wiki says like this

在某些情况下,使用静态限定符可能是有益的。然而在其他情况下,这确实是一个非常糟糕的主意,并且会产生意想不到的后果。

使用static的技术结果很明显:在类的所有实例中只共享一个Log引用。这显然是记忆效率高的;无论创建多少个实例,只需要一个引用(4或8个字节)。它还具有CPU效率;在首次引用类时,查找Log实例所需的查找只执行一次。