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