是否有类似于sl4fj的通用字符串替换函数?


83

使用sl4fj如果我想构造一个字符串消息,有一种很好的方法可以利用替换。例如,可能是这样的:

logger.info("Action {} occured on object {}.", objectA.getAction(), objectB);

如果需要多个替换,则类似于:

logger.info("Action {} occured on object {} with outcome {}.", 
    new Object[]{objectA.getAction(), objectB, outcome});

我的问题是:有没有一种通用的方式来创建字符串(而不仅仅是slf4j日志消息)?就像是:

String str = someMethod("Action {} occured on object {}.", objectA.getAction(), objectB);

要么

String str = someMethod("Action {} occured on object {} with outcome {}.", 
    new Object[]{objectA.getAction(), objectB, outcome});

如果它在标准Java库中,那么“ someMethod”将是什么?


1
感谢下面的答案。另外,我发现这里已经问过这个问题:stackoverflow.com/questions/3114021。很抱歉张贴了差不多重复的副本。
kmccoy 2011年

Answers:


110

字符串格式

String str = String.format("Action %s occured on object %s.",
   objectA.getAction(), objectB);

要么

String str = String.format("Action %s occured on object %s with outcome %s.",
   new Object[]{objectA.getAction(), objectB, outcome});

您还可以使用数字位置,例如在以下位置切换参数:

String str = String.format("Action %2$s occured on object %1$s.",
   objectA.getAction(), objectB);

44

您可以使用String.formatMessageFormat.format

例如,

MessageFormat.format("A sample value {1} with a sample string {0}", 
    new Object[] {"first", 1});

或简单地

MessageFormat.format("A sample value {1} with a sample string {0}", "first", 1);

1
MessageFormat非常通用且功能强大,但是对于简单的替换,String.format可能会更简单且受限制的程度较小(例如,MessageFormat需要将单引号加倍)。

1
新的Integer(1)替换为上面的1也将起作用。
TechnoCrat 2015年

25

如果您正在寻找可以用值替换String中的一堆变量的解决方案,则可以使用StrSubstitutor

 Map<String, String> valuesMap = new HashMap<>();
 valuesMap.put("animal", "quick brown fox");
 valuesMap.put("target", "lazy dog");
 String templateString = "The ${animal} jumped over the ${target}.";
 StrSubstitutor sub = new StrSubstitutor(valuesMap);
 String resolvedString = sub.replace(templateString);

它遵循一种普遍接受的模式,即可以将带有变量的映射与未解析的字符串一起传递给值,并返回解析的字符串。


20

我建议使用org.slf4j.helpers.MessageFormatter。借助它,可以创建一种使用与slf4j完全相同的格式样式的实用方法:

// utillity method to format like slf4j
public static String format(String msg, Object... objs) {
    return MessageFormatter.arrayFormat(msg, objs).getMessage();
}

// example usage
public static void main(String[] args) {
    String msg = format("This msg is {} like slf{}j would do. {}", "formatted", 4,
            new Exception("Not substituted into the message"));

    // prints "This msg is formatted like slf4j would do. {}"    
    System.out.println(msg); 
}

注意:如果数组中的最后一个对象是一个Exception,它将不会在消息中被替换,就像使用slf4j记录器一样。可通过访问Exception MessageFormatter.arrayFormat(msg, objs).getThrowable()


3
我认为这不是一个很好的通用答案,但是实际上已经达到了要求的程度。
Michael Piefel '16

3
我发现这是正确的答案。就性能而言,这应该是最好的。
萨莎(Sasa)

1
最佳答案,因为它使用了所要求的确切语法。
克里斯多夫(Christoph)

坦白说,恕我直言,这是实际上与原始问题匹配的唯一答案...让我
震惊,

0

我选择包装Log4j2 ParameterizedMessage,它最初是由Joern Huxhorn为Lilith编写的:

public static String format(final String messagePattern, Object... arguments) {
    return ParameterizedMessage.format(messagePattern, arguments);
}

它专注于消息格式,与SLF4J MessageFormatter不同,后者包含Throwable的不必要处理。

参见Javadoc:

处理由包含表示每个可替换标记的'{}'格式字符串和参数组成的消息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.