Есть ли общая функция подстановки строк, аналогичная sl4fj?

85

С 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"?

kmccoy
источник
1
Спасибо тем, у кого есть ответы ниже. Кроме того, я обнаружил, что этот вопрос уже задавался здесь: stackoverflow.com/questions/3114021 . Извините, что опубликовал более или менее дубликат.
kmccoy

Ответы:

113

String.format

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);
Скрам Мейстер
источник
45

Вы можете использовать string.Format или MessageFormat.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 требует удвоения одинарных кавычек).
Kat
1
new Integer (1) заменен только на 1, то тоже будет работать.
TechnoCrat
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); 
}

Примечание . Если последний объект в массиве является исключением, он не будет заменен в сообщении, как и в случае с регистратором slf4j. Исключение будет доступно через MessageFormatter.arrayFormat(msg, objs).getThrowable().

Пит
источник
3
Я бы сказал, что это не очень хороший универсальный ответ, но на самом деле он вполне соответствует тому, о чем спрашивали.
Майкл Пифель,
3
Я считаю, что это правильный ответ. Это должно быть лучшим с точки зрения производительности.
Sasa
1
Лучший ответ, поскольку он использует точный синтаксис, который задан в вопросе.
Кристоф
честно говоря, ИМХО, это единственный ответ, который на самом деле соответствует исходному вопросу ... лучше меня, почему он сейчас на четвертом месте ...
raner
0

Я выбираю обернуть Log4j2 ParameterizedMessage, который изначально был написан для Lilith Джорном Хаксхорном:

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

Это внимание на формат сообщения, в отличие от SLF4J MessageFormatter , который содержит ненужную обработку Throwable.

См. Javadoc:

Обрабатывает сообщения, которые состоят из строки формата, содержащей '{}' для представления каждого заменяемого токена и параметров.

чжоуцзи
источник