我们必须一直为日志输出构建字符串等等。在JDK版本中,我们已经学习了什么时候使用StringBuffer(许多追加,线程安全)和StringBuilder(许多追加,非线程安全)。
使用String.format()有什么建议?它是有效的,还是我们被迫坚持在性能很重要的一行程序中使用连接?
例如,丑陋的老式风格,
String s = "What do you get if you multiply " + varSix + " by " + varNine + "?";
vs.整洁的新样式(字符串。格式,可能更慢),
String s = String.format("What do you get if you multiply %d by %d?", varSix, varNine);
注意:我的特定用例是代码中的数百个“一行”日志字符串。它们不涉及循环,所以StringBuilder太重量级了。我对String.format()特别感兴趣。
在您的示例中,性能可能没有太大不同,但还有其他问题需要考虑:即内存碎片。连接操作也在创建一个新字符串,即使它是临时的(GC需要时间,而且工作量更大)。String.format()可读性更强,涉及的碎片更少。
此外,如果你经常使用特定的格式,不要忘记你可以直接使用Formatter()类(所有String.format()所做的是实例化一个使用Formatter实例)。
此外,还应该注意其他一些事情:小心使用substring()。例如:
String getSmallString() {
String largeString = // load from file; say 2M in size
return largeString.substring(100, 300);
}
这个大字符串仍然在内存中,因为这就是Java子字符串的工作方式。一个更好的版本是:
return new String(largeString.substring(100, 300));
or
return String.format("%s", largeString.substring(100, 300));
如果你同时做其他事情,第二种形式可能更有用。
To expand/correct on the first answer above, it's not translation that String.format would help with, actually.
What String.format will help with is when you're printing a date/time (or a numeric format, etc), where there are localization(l10n) differences (ie, some countries will print 04Feb2009 and others will print Feb042009).
With translation, you're just talking about moving any externalizable strings (like error messages and what-not) into a property bundle so that you can use the right bundle for the right language, using ResourceBundle and MessageFormat.
Looking at all the above, I'd say that performance-wise, String.format vs. plain concatenation comes down to what you prefer. If you prefer looking at calls to .format over concatenation, then by all means, go with that.
After all, code is read a lot more than it's written.
仅从日志的角度看另一个角度。
我在这个帖子上看到了很多关于登录的讨论,所以我想在回答中加入我的经验。也许有人会觉得有用。
我猜使用格式化程序进行日志记录的动机来自于避免字符串连接。基本上,如果你不打算记录它,你不希望有字符串连接的开销。
实际上不需要concat/format,除非您想记录日志。假设我这样定义一个方法
public void logDebug(String... args, Throwable t) {
if(debugOn) {
// call concat methods for all args
//log the final debug message
}
}
在这种方法中,如果它是一个调试消息并且debugOn = false,则根本不会真正调用canat /formatter
尽管在这里使用StringBuilder而不是formatter会更好。我们的主要动机就是避免这些。
同时,我不喜欢为每个日志语句添加“if”块
它会影响可读性
减少单元测试的覆盖率——当你想要确保每一行都经过测试时,这会让人感到困惑。
因此,我更喜欢用上面的方法创建一个日志实用程序类,并在任何地方使用它,而不用担心性能损失和其他与之相关的问题。