记录器与 System.out.println

Posted

技术标签:

【中文标题】记录器与 System.out.println【英文标题】:Logger vs. System.out.println 【发布时间】:2011-02-14 13:46:12 【问题描述】:

我正在为 Eclipse 使用 PMD 插件,但在使用 System.out.println() 时它给了我一个错误的解释:

使用System.(out|err).print,考虑使用记录器。

我的问题是 - 什么是记录器?它是如何打印到屏幕上的?为什么更好?

【问题讨论】:

另见这个最近的问题:***.com/questions/2746578/advantage-of-log4j 【参考方案1】:

见this short introduction to log4j。

问题在于使用System.out 打印调试或诊断信息。这是一种不好的做法,因为您无法轻松更改日志级别、将其关闭、自定义等。

但是,如果您合法地使用System.out 向用户打印信息,那么您可以忽略此警告。

【讨论】:

我会将答案扩展为“[...] 将信息打印给用户或其他进程,然后您可以忽略此警告”。想想 Unix 进程将输出通过管道传输到另一个,正是System.out 的概念赋予了这一点。【参考方案2】:

如果您在应用程序的 main() 方法中使用 System.out|err.println(..) 在控制台上打印用户信息,那么您不会做错任何事。您可以通过插入注释“//NOPMD”来删除该消息。

System.out.println("Fair use of System.out.println(..).");// NOPMD

为此目的,PMD 违规大纲中有一个“标记为已审核”选项。

当然你可以用下面的代码 sn-p 来欺骗 PMD:

PrintStream out=System.out;
out.println("I am fooling PMD.");  

在你的 main() 方法之外使用一个日志系统,例如 Log4j。

更新:

您还可以修改 PMD 规则“SystemPrintln”以使用以下 XPath:

//MethodDeclaration[@MethodName!="main"]//Name[
starts-with(@Image, 'System.out.print')
or
starts-with(@Image, 'System.err.print')
] | //Initializer//Name[
starts-with(@Image, 'System.out.print')
or
starts-with(@Image, 'System.err.print')
]

这将忽略代码中任何名为“main”的方法中的 System.out.println 等,但会检查初始化代码中的 System.out.println。 我喜欢这个,因为从我的角度来看,System.out.println 在方法“main(String args[])”中是安全的。但是请谨慎使用,我必须检查在 AST 中 System.out.println 也可能出现的位置,并且必须适应 XPath。

【讨论】:

【参考方案3】:

Loggers 有多个级别的日志记录。

如果我们正在编写一个真正的短程序,仅用于学习目的System.out.println 可以,但是当我们开发高质量的软件项目时,我们应该使用专业的记录器,并且应该避免 SOP。

专业的记录器提供不同级别的记录和灵活性。我们可以相应地获取日志消息。例如,X 组消息应仅在 PRODUCTION 上打印,Y 组消息应在 ERROR 上打印,等等。

我们在System.out 中重定向消息的选项有限,但对于记录器,您有提供多个选项的附加程序。我们甚至可以创建一个自定义输出选项并将其重定向到该选项。

【讨论】:

【参考方案4】:

此链接提供了有关如何使用 Log4j 的更简洁信息:Don't use System.out.println! 但是它只有一个小缺陷,您不应该将库放在 /jre/lib/ext 中,而是将其放在应用程序的运行时类路径中并发布一起来。

优点是您可以使用日志记录级别来指示信息的重要性,以便您可以在外部配置在输出中显示/隐藏哪些级别(这样您就不会被 - 毕竟 -无用信息),输出应该是什么样子(例如,包括时间戳、线程 ID、类名、方法名等)以及输出应该写入到哪里(例如控制台、文件、电子邮件等)以及在以下情况下例如文件还应该如何创建它们(例如按年、月和/或日分组)。

有几种记录器实现,如 Java SE 的内置 java.util.logging.Logger、方便的 Apache Commons Logging、流行的 Apache Log4j、其后继 Logback 等。您可以使用 Slf4j 作为额外的抽象层来切换在任何需要时在这些记录器之间进行。

【讨论】:

【参考方案5】:

似乎 PMD 假设您正在调用 System.out.println() 以进行调试;诸如“我在你的方法中,正在执行你的 codez”之类的东西。

如果你这样做,你将有更好的时间写入像 Log4J 这样的记录器,因为它有多个流选项,而不仅仅是屏幕。

但是,如果您正在执行控制台应用程序并在其中调用 System.out,请忽略该警告。

【讨论】:

【参考方案6】:

System.out.println 不好用,不能配置。相反,Logger 可以配置为登录各个级别。它还有很多其他功能。

【讨论】:

以上是关于记录器与 System.out.println的主要内容,如果未能解决你的问题,请参考以下文章

如果发现一个逗号分隔记录与另一个逗号分隔记录匹配,则获取记录

MySQL触发器:在插入之前将记录与先前的记录进行比较

与记录器线程的多线程应用程序交互

记录与 print() + 记录最佳实践的优势

如何找到与其他记录组匹配的记录组(关系划分?)

用于计算记录数的 SQL 查询必须与记录总数匹配