Java 如何删除System.out.println';来自代码库的消息
我们有一个庞大的(旧的遗留java)代码库,其中许多文件(大约5k)都有System.out.println。出于清理/性能原因,我们计划删除它们。我们如何编写一个脚本来替换它们而不在代码中引入任何问题?脚本不能盲目删除它们,因为以下情况可能是一个问题:Java 如何删除System.out.println';来自代码库的消息,java,performance,scripting,code-cleanup,Java,Performance,Scripting,Code Cleanup,我们有一个庞大的(旧的遗留java)代码库,其中许多文件(大约5k)都有System.out.println。出于清理/性能原因,我们计划删除它们。我们如何编写一个脚本来替换它们而不在代码中引入任何问题?脚本不能盲目删除它们,因为以下情况可能是一个问题: if () some.code... else System.out.println(...); DB.close(); 我想用“;”来代替它们。这将解决上述问题。你看到其他问题了吗?有什么其他的建议吗? < P>我个人会使用 {}
if ()
some.code...
else
System.out.println(...);
DB.close();
我想用“;”来代替它们。这将解决上述问题。你看到其他问题了吗?有什么其他的建议吗? < P>我个人会使用<代码> {} /COD>,但我认为它是一样的。 < P>你有没有考虑过这个愚蠢的例子:
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();
与
您可以使用一个包含打印语句的调试版本和不包含打印语句的发布版本
基本上,这个想法是创建一个带有最终静态布尔值的最终静态类,您可以在编译时将其用作开关
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语句可能会更改某些对象的状态。正如他所建议的,在发布模式下,您可以使用条件编译来打印空对象,而不是完全删除打印。Log4E是一个eclipse插件,具有“Replace System.out.println()”功能。 它会很高兴地将那些讨厌的println调用转换为log4j调用。
它甚至会用日志级别的检查来包装它们。您可以从调用Systems.setOut开始,并传入您自己的OutputStream,而它什么也不做。这将帮助您查看是否有性能增益。这比移除它们更安全(奥斯卡指出了这一点——编码的副作用)。如果性能增益是可忽略的,那么您可能希望将精力集中在其他地方 我的上述方法存在两个问题:
不过,这是一个很好的快速测试,看看您是否获得了期望的性能提升。我用perl编写了一个正则表达式,将字符串“System.out.println”替换为“;//System.out.println”。我相信很少有这样的情况会破坏构建。它将变成一个“else;”,编译成零字节码指令
看起来这就是你的建议。这对我来说很有效——除非你在同一行上有其他语句。然而,这种风格一开始就很糟糕(我知道我没有这么做)。扩展奥斯卡的概念,你可以做得更好
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实现,否则它将按预期工作。这样,您就不必查找和替换代码中的任何内容。您是否考虑过编辑这些源文件以删除这些行 您可能会发现,开发人员只需要几天的时间就可以完成并摆脱其中的大部分。我们也有类似的问题,我只是起得很早,翻阅了我们所有的文件,清理垃圾 我使用Eclipse和“保存时清理”功能同时清理导入和其他内容
这是一件很有治疗作用的事情 教皇模式:-)这就是(在许多其他原因中)为什么我总是使用{}即使是一行的东西!(我知道这是遗产,可能不是你做的)。我会用{}代替它们;但两者都是好的。教皇回声:我正要评论完全相同的事情。我知道,可能代码中没有。然而,由于有很多文件和遗产(这几乎总是意味着不好),我不想冒险。我很喜欢,奥斯卡。我必须说,我想得很好。令人震惊的是,我不得不打破NetBeans并尝试它。好主意-如果您将“愚蠢的情况”从object.stateChanged()更改为object.changeState(),则会更容易看到,否则它听起来像是对对象的查询,我一直认为更改对象状态没有任何意义。。。个人习惯…很有趣。可以使用记录器处理新的打印语句,并完全禁用系统。使用此选项退出。:)那么,我们可以称之为“奥斯卡·雷耶斯+比尔蜥蜴”方法吗P:P+1表示这是假设没有其他代码正在进行放样;)只是开玩笑。这是一个很好的建议。可能是最简单最快的方法。如果不需要合法的控制台输出,那么这绝对是一条出路。
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) {}
} );
}
}