Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 定义记录器非静态的缺点_Java_Logging - Fatal编程技术网

Java 定义记录器非静态的缺点

Java 定义记录器非静态的缺点,java,logging,Java,Logging,对此答案的评论强烈建议不要将记录器用作实例成员变量。我能想到两个负面的副作用: 1) 超类使用子类的记录器记录日志 2) 无法序列化对象(除非标记为瞬态) 但是,如果序列化是不必要的,并且使用子类名称进行日志记录也不是问题,那么还有什么其他原因可以避免吗?我认为,在将记录器变量定义从一个类复制到另一个类时,它减少了样板代码,避免了复制粘贴错误。甚至Spring框架(我相信它有很好的编码标准)也使用这种方法。尝试调试一个错误,当错误真正记录在子类中时,您会看到超类生成的消息。我见过一些情况,其中开

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


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

尝试调试一个错误,当错误真正记录在
子类中时,您会看到
超类生成的消息。我见过一些情况,其中开发人员创建了一个
LoggingUtils
类,该类生成的消息通常与日志框架已经烘焙的内容重复


我看到的使用共享日志实例的唯一真实情况是Apache commons HttpClient logger
HttpClient.wire,它在几个类之间共享,用于记录通过客户端发送的请求和响应的内容。这种特殊的日志记录情况不会记录包的实际实现信息,而是记录整个http“事务”的信息。

另一个可能是次要的缺点:内存浪费,尤其是当您有大量实例时,每个日志都有自己的日志

当然,与使用子类名称的超类日志的主要区别在于,每个类成员都有一个
日志
对象。根据使用日志记录的类的数量,这可能是大量的日志记录程序,因此内存膨胀可能是一个问题


另外,从抽象的角度来看,记录器确实属于该类,并且可以在所有实例之间共享,而不是每个实例都需要自己的私有副本,因此将其声明为静态是有意义的。把你的问题翻过来,让它成为非静态的有什么好处?(能够将
getClass()
传递到
getLogger()
调用中,而不是传递类常量,这是我唯一能想到的事情,这是一件非常微小的事情)。

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


从设计的角度来看,记录器并不是对象的真正属性,因为它们通常是关于系统的元信息,而不是系统本身中的业务信息。
记录器
发动机
变速箱
不同,它实际上不是
汽车
对象的一部分。将记录器与对象绑定为成员(在大多数情况下)在语义上没有任何意义。

您可能想看看这些讨论主题的页面:


主要问题之一是清理内存实例。即使您不创建类的对象,因为您使用logger的静态实例,也会有对这些对象的引用

正如apache所说,这会保留引用,因此它们在使用后不会被释放

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


使用static的技术结果是显而易见的:在类的所有实例中只共享一个日志引用。这显然是内存有效的;无论创建了多少实例,都只需要一个引用(4或8字节)。它还具有CPU效率;查找日志实例所需的查找仅在第一次引用该类时执行一次。

Log4j(我假定其他日志框架也有)拥有一个日志记录器池。因此,只创建一个具有相同名称的实例。因此,内存消耗与静态记录器相同。如果这是一个缺点,那么最好使用它singelton@martsraits:否,因为您的类持有一个指向池instanceLog4j的新引用(指针)(我假定其他日志框架也持有一个日志记录器池)。因此,只创建一个具有相同名称的实例。因此,内存消耗与静态记录器相同。一些记录器具有缓存机制。Log4j使用
LogManager
类缓存记录器,因此使用静态和非静态记录器的开销是相同的。@VarunAchar-Right-实际
记录器
实例的内存开销通常是缓存的。我在这里主要得到的是,如果
记录器
不是
静态的
,那么对管理器或记录器实例的引用将在所有实例中重复,并且仍然需要为每个创建的实例调用
记录器
(即从缓存中)。再说一次,可能不重要,但值得注意。而且,它确实使用了更多的内存。字段本身(对Logger对象的引用)是4个字节(至少),每个实例中都要存储这些字节。