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

时间:2009-02-21 03:41:08

标签: java performance scripting code-cleanup

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

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

我正在考虑用';'替换它们。这将照顾上述情况。你还有其他问题吗?还有其他建议吗?

8 个答案:

答案 0 :(得分:25)

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

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

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

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

使用NullObject模式创建一个空对象:

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();

答案 1 :(得分:11)

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

答案 2 :(得分:8)

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

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实现替换,否则它将按预期工作。这样您就不必在代码中查找和替换任何内容。

答案 3 :(得分:6)

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

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

  1. 您要保留的任何System.out.printlns也将消失
  2. 字符串连接仍然会发生(这可能很昂贵,具体取决于有多少)
  3. 然而,这是一个很好的快速测试,看看你是否获得了你正在寻找的性能提升。

答案 4 :(得分:2)

您可以使用conditional compilation来使用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语句可能会更改某个对象的状态。您可以使用条件编译在处于释放模式时打印到空对象,正如他所建议的那样,而不是完全删除打印件。

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

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

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

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