如何从代码库中删除System.out.println

我们有一个庞大的(旧的遗留Java)代码库,其中许多文件(大约5k)都有System.out.println。 我们计划因清理/性能原因删除它们。 我们如何编写一个脚本来替换它们而不会在代码中引入任何问题? 脚本不能盲目删除它们,因为以下情况可能是一个问题:

if () some.code... else System.out.println(...); DB.close(); 

我想用’;’代替它们。 这将照顾上述情况。 你还有其他问题吗? 还有其他建议吗?

你考虑过这个愚蠢的案子:

 System.out.println(" Print " + object.changeState() ); 

我认为它不会发生但是偶然的机会是println执行的方法实际上正在执行系统所依赖的某些操作,并且可能会引入微妙的错误(相信我或不相信,但我亲眼目睹了这一点)

可能会用记录器替换并禁用记录器。

或者使用NullObject模式创建一个null对象:

 public final class DevNull { public final static PrintStream out = new PrintStream(new OutputStream() { public void close() {} public void flush() {} public void write(byte[] b) {} public void write(byte[] b, int off, int len) {} public void write(int b) {} } ); } 

并取代

  System.out.println(); 

  DevNull.out.println(); 

Log4E是一个带有“Replace System.out.println()”function的eclipse插件。 它会愉快地将所有那些讨厌的println调用转换为log4j调用。 它甚至会用日志级别检查来包装它们。

扩展奥斯卡的概念,你可以做得更好恕我直言:

 if(!DEBUG) { System.setOut( new PrintStream(new OutputStream() { public void close() {} public void flush() {} public void write(byte[] b) {} public void write(byte[] b, int off, int len) {} public void write(int b) {} } ); } } 

在这种情况下,如果您未处于调试模式或任何其他模式,则默认系统输出将在内部使用devNull实现替换,否则它将按预期工作。 这样您就不必在代码中查找和替换任何内容。

您可以从调用Systems.setOut开始,然后传入您自己的OutputStream,它什么都不做。 这将帮助您了解是否有性能提升。 这比删除它更安全(因为Oscar指出 – 由副作用编码)。 如果性能增益可以忽略不计,那么您可能希望将工作重点放在其他地方。

我上面的方法有两个问题:

  1. 你想要保留的任何System.out.printlns也会消失
  2. 字符串连接仍然会发生(这可能很昂贵,具体取决于有多少)

然而,这是一个很好的快速测试,看看你是否获得了你正在寻找的性能提升。

您可以使用条件编译来使用print语句和没有它们的发布版本进行调试构建。

基本上,我们的想法是创建一个带有最终静态布尔值的最终静态类,您可以在编译时将其用作切换。

 public final class Debug { //set to false to allow compiler to identify and eliminate //unreachable code public static final boolean ON = true; } 

然后你可以用你的所有System.out.println语句替换掉

 if(Debug.ON) { System.out.println... } 

由于编译器将忽略任何无法访问的代码分支,因此在执行发布构建时可以设置ON = false ,并且将从字节码中排除print语句。

注意:这不涉及Oscar指出的情况,其中print语句可能会改变某个对象的状态。 您可以使用条件编译在处于释放模式时打印到空对象,如他所建议的那样,而不是完全删除打印件。

就个人而言,我会使用{}代替,但我认为它的工作原理相同。

我在perl中编写了一个正则表达式,用“; System.out.println”替换字符串“System.out.println”。 我认为很少有这种情况会破坏构建。 它只会变成一个“else;”,它被编译为零字节码指令。

看起来这就是你提出的。 它对我有用 – 除非你在同一行上有其他陈述。 然而,开始时这是不好的风格(我知道我没有这样做)。

您是否考虑过编辑这些源文件以删除这些行?

您可能会发现,只有开发人员需要花费几天时间才能完成并删除大部分内容。 我们有一个类似的问题,我刚刚起得很早,并通过我们所有的文件摆脱了垃圾。

我使用Eclipse和清理保存function来同时清理导入和填充。

这是一个非常有待治疗的事情!