Чи існує загальна функція заміщення рядків, подібна до 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

Відповіді:


110

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);

44

Ви можете використовувати 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
нове ціле число (1), замінене лише на 1 вище, теж буде працювати.
TechnoCrat

25

Якщо ви шукаєте рішення, де ви можете замінити купу змінних у рядку значеннями, ви можете використовувати 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
Я б стверджував, що це не є доброю загальною відповіддю, але насправді цілком до мети того, про що запитували.
Michael Piefel

3
Я вважаю, що це точно правильна відповідь. Це повинно бути найкращим з точки зору продуктивності.
Саша

1
Найкраща відповідь, оскільки вона використовує точний синтаксис запитуваного питання.
Крістоф,

чесно кажучи, IMHO це єдина відповідь, яка насправді відповідає вихідному питанню ... б'є мене, чому саме зараз вона посіла четверте місце ...
raner

0

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

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

Це фокус на форматі повідомлення, на відміну від SLF4J MessageFormatter, який містить непотрібну обробку Throwable.

Дивіться Javadoc:

Обробляє повідомлення, які складаються з рядка формату, що містить "{}", що представляє кожен змінний маркер та параметри.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.