调试:使用System.out.println()还是不使用System.out.println()

5

这是我的问题。更具体地说,我正在尝试适应Eclipse的调试器,并且想知道在某些情况下是否仍然可以将打印输出到控制台,或者它是否被认为是完全应该避免的不良实践。此外,有哪些方法可以被视为调试的良好方法?


1
如果使用日志记录库过于繁琐,那么至少编写一个调试消息例程,调用System.[err|out].println()。这样,您可以稍后在一个地方注释掉println(),以整理代码。稍后删除println()总是很麻烦的。 - Marvo
这真的取决于具体情况。有些情况下,System.out.println()实际上比调试器更好。您可能还对DoodleDebug感兴趣:http://scg.unibe.ch/wiki/projects/DoodleDebug - Cedric Reichenbach
5个回答

13

使用 System.err.println() 代替。

为什么?

System.out.println() 经常被重定向到文件或其他输出,而这几乎总是打印在控制台上。它更容易进行调试,也是正确的做法。


编辑 (警告: 主观):

由于您问到是否完全避免使用 System.out.println:我不相信有任何必须始终避免的事情,无论是使用 goto,用蓝屏崩溃计算机还是其他。有时你只需要一种快速且简单粗暴的方法来快速完成小事情,即使正常的“好”方法多好,花费1小时去尝试正确的方式,而不是一个5分钟的修复,也根本不值得。在决定是否应该使用某个东西时,请判断自己的判断力,但永远不要对自己设定规则,比如“我永远不会使用goto!”。 :)

编辑 2(示例):

假设您正在调试一个崩溃的驱动程序,并怀疑正在执行不应执行的 if 语句。与其花三个小时找出如何使用 ZwRaiseHardError 显示消息框,不如在 if 语句内部调用 KeBugCheck 并使系统崩溃。当然,您会重新启动计算机,但除非您的重新启动需要几个小时,否则您刚刚节省了这么多时间。


我喜欢你的编辑所提供的见解。感谢反馈 :) - James P.
3
-1 就是为了在5分钟内写一个hack,却要浪费1小时来正确编写它,并节省6小时的调试时间。 - Falmarri
6
如果我调试一段五分钟的代码花费了超过十分钟,我会选择正确的方法,而不是花费六个小时来修复它。但如果你要花费一小时才能找出如何以“正确”的方式显示错误,而你只需在30秒内用 println 命令就可以完成并在五分钟内完成工作,那我会为你感到非常抱歉。 (我会抱怨这个 -1 分数,但这毕竟是个人意见,所以随意持不同意见。) :) - user541686
现在需要一个小时,但到你需要按正确方式去做时,可能需要六个小时,这可能是最好的情况,这取决于有多少其他开发人员在其上构建了烂摊子,整个系统现在都依赖于它。更不用说,其他想要按正确方式做事的可怜家伙现在无法这样做,因为你的hack阻止了他,并且必须花费一小时的时间来找出一个不会失败的兼容性hack... 真是的...我永远不会理解Java开发人员。 - BrainSlugs83

7

最好的选择是使用一个日志库(当然,这会给您的项目增加额外的依赖)。例如,可以查看commons-logging。 主要优点是您可以在DEBUG级别中编写调试消息,当您部署代码时,只需配置记录器跳过这些消息(而不是在代码中搜索所有System.out.println的出现)。 另一个巨大的优点是,日志记录器通常可以配置为在任何地方写入(甚至发送电子邮件或短信),而无需触及您的代码。


1
关于使用日志库,我强烈建议使用SLF4J。它提供了一个易于使用的包装器,可以围绕实际使用的日志库进行操作,从而使切换使用的日志库更加容易。此外,越来越多的库正在使用它,因此您可能无论如何都需要获取其实现。 - deterb

3
  1. 小细节:如果您的程序通过System.out向控制台输出实际有用的信息,则建议将调试信息打印到System.err而非System.out。

  2. 通常应尽可能多地进行调试(最好使用一些标准记录器,如log4j)。这样既便于开发程序时进行调试,也便于在已发布的代码中更轻松地进行调试。好处是您的代码保持不变,而且无需添加debugf打印语句,但默认情况下日志配置可以关闭日志记录,直到真正需要它(或至少降低日志级别)。

  3. 至于一般简单的“随意打印”调试,它有时可能是调试的最快方法之一,但它不应该是唯一/主要的调试方法。

    为什么它有用?除了其他原因之外,因为在调试器中运行Java程序可能比在其外部慢得多;或者因为您的错误表现在一个不能轻松复制到Eclipse调试器中的环境/情况中。


1

如果调试打印行在修复错误后不会留在代码中,那么请按照你最方便的方式操作。使用System.err.println()的Lambert建议是个好主意,因为你可以将其与程序产生的其他输出区别开来。如果调试打印行将留在你的代码中,那么我建议使用像log4j这样的日志框架。这样,你可以根据是否尝试调试某些内容或仅在生产环境中运行而调整输出级别。使用log4j时,请确保以正确的级别输出内容。不要只记录所有INFO信息。


0

我在调试时使用System.out.println,以便在出现问题或方法启动时通知我,以确保一切正常工作,但当我发布程序时,我总是将其删除,因为它会减慢程序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接