如何从代码库中删除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指出 – 由副作用编码)。 如果性能增益可以忽略不计,那么您可能希望将工作重点放在其他地方。
我上面的方法有两个问题:
- 你想要保留的任何System.out.printlns也会消失
- 字符串连接仍然会发生(这可能很昂贵,具体取决于有多少)
然而,这是一个很好的快速测试,看看你是否获得了你正在寻找的性能提升。
您可以使用条件编译来使用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来同时清理导入和填充。
这是一个非常有待治疗的事情!