有没有办法使用SLF4J风格的格式化函数构建Java字符串?

2022-09-01 20:12:22

我听说使用StringBuilder比使用字符串串联更快,但我厌倦了一直与StringBuilder对象摔跤。我最近接触到了SLF4J日志记录库,与String.format相比,我喜欢其格式的“只是做正确的事情”的简单性。有没有一个库可以让我写这样的东西:

int myInteger = 42;
MyObject myObject = new MyObject();  // Overrides toString()
String result = CoolFormatingLibrary.format("Simple way to format {} and {}",
    myInteger, myObject);

另外,是否有任何原因(包括性能,但不包括对日期和有效数字格式的细粒度控制)为什么我可能想要使用String.format而不是这样的库(如果它确实存在)?


答案 1

虽然“接受”的答案很好,但如果(像我一样)对Slf4J风格的语义感兴趣,那么正确的解决方案是使用Slf4J的MessageFormatter。

下面是一个示例用法代码段:

public static String format(String format, Object... params) {
    return MessageFormatter.arrayFormat(format, params).getMessage();
}

(请注意,此示例将丢弃类型的最后一个参数Throwable)


答案 2

对于一次串联字符串,旧的可靠是完全可以的(它实际上由编译器转换为)。"str" + param + "other str"StringBuilder

StringBuilders主要有用,如果你必须继续向字符串添加内容,但你不能把它们全部放入一个语句中。例如,取一个 for 循环:

String str = "";
for (int i = 0; i < 1000000; i++) {
    str += i + " "; // ignoring the last-iteration problem
}

这将比等效的StringBuilder版本运行得慢得多:

StringBuilder sb = new StringBuilder(); // for extra speed, define the size
for (int i = 0; i < 1000000; i++) {
    sb.append(i).append(" ");
}
String str = sb.toString();

但这两者在功能上是等效的:

String str = var1 + " " + var2;
String str2 = new StringBuilder().append(var1).append(" ").append(var2).toString();

说了这么多,我的实际答案是:

看看java.text.MessageFormat。来自 Javadocs 的示例代码:

int fileCount = 1273;
String diskName = "MyDisk";
Object[] testArgs = {new Long(fileCount), diskName};

MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0} file(s).");

System.out.println(form.format(testArgs));

输出:

The disk "MyDisk" contains 1,273 file(s).

还有一个静态格式方法,不需要创建对象。MessageFormat

所有这些库都将归结为最基本级别的字符串串联,因此彼此之间不会有太大的性能差异。