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

回答:


110

String.format

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

Or

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

You can also use numeric positions, for example to switch the parameters around:

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

44

You can use String.format or MessageFormat.format

E.g.,

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

or simply

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

1
MessageFormat is very versatile and powerful, but for simple replacements, String.format will likely be simpler and less restricted (eg, MessageFormat requires single quotes to be doubled).
Kat

1
new Integer(1) replaced with only 1 in above then too will work.
TechnoCrat

25

If you are looking for a solution where you can replace a bunch of variables in a String with values, you can use 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);

It follows a generally accepted pattern where one can pass a map with variables to values along with the unresolved String and it returns a resolved String.


20

I would suggest to use org.slf4j.helpers.MessageFormatter. With the help of it one can create a utillity method that uses the exact same formatting style as 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); 
}

Note: If the last object in the array is an Exception it will not be substituted in the message, just like with an slf4j logger. The Exception would be accessible via MessageFormatter.arrayFormat(msg, objs).getThrowable().


3
I’d argue this is not a good general-purpose answer, but actually quite to the point of what was asked, though.
Michael Piefel

3
I find this exactly the right answer. This should be the best in terms of performance.
Sasa

1
Best answer as it uses the exact syntax the question asked for.
Christoph

frankly, IMHO this is the only answer that actually matches the original question... beats me why it's ranked on fourth place right now...
raner

0

I choose wrap the Log4j2 ParameterizedMessage which was originally written for Lilith by Joern Huxhorn:

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

It is focus on message format, unlike SLF4J MessageFormatter which contains unnecessary processing of Throwable.

See the Javadoc:

Handles messages that consist of a format string containing '{}' to represent each replaceable token, and the parameters.

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.