Как форматировать строки в Java
Примитивный вопрос, но как мне форматировать строки подобным образом:
"Шаг {1} из {2}"
путем замены переменных с помощью Java? В C # это просто.
Переведено автоматически
Ответ 1
Взгляните на String.format. Однако обратите внимание, что для этого требуются спецификаторы формата, аналогичные спецификаторам семейства функций printf в C - например:
String.format("Hello %s, %d", "world", 42);
Вернет "Hello world, 42". Вы можете найти это полезным при изучении спецификаторов формата. Энди Томас-Крамер был достаточно любезен, чтобы оставить эту ссылку в комментарии ниже, которая, похоже, указывает на официальную спецификацию. Наиболее часто используемые из них::
- %s - вставить строку
- %d - вставить целое число со знаком (десятичное)
- %f - вставить действительное число, стандартная запись
Это радикально отличается от C #, который использует позиционные ссылки с необязательным спецификатором формата. Это означает, что вы не можете делать такие вещи, как:
String.format("The {0} is repeated again: {0}", "word");
... фактически без повторения параметра, переданного в printf/format . (смотрите комментарий Scrum Meister ниже)
Если вы просто хотите распечатать результат напрямую, вы можете найти System.out.printf (PrintStream.printf) по своему вкусу.
Ответ 2
В дополнение к String.format, также взгляните на java.text.MessageFormat
. Формат менее лаконичный и немного ближе к приведенному вами примеру C #, и вы также можете использовать его для синтаксического анализа.
Например:
int someNumber = 42;
String someString = "foobar";
Object[] args = {new Long(someNumber), someString};
MessageFormat fmt = new MessageFormat("String is \"{1}\", number is {0}.");
System.out.println(fmt.format(args));
Более приятный пример использует преимущества улучшений varargs и автоматической упаковки в Java 1.5 и превращает вышеприведенное в однострочное:
MessageFormat.format("String is \"{1}\", number is {0}.", 42, "foobar");
MessageFormat
немного удобнее использовать i18nized множественное число с модификатором выбора. Чтобы указать сообщение, которое правильно использует форму единственного числа, когда переменная равна 1, и множественное число в противном случае, вы можете сделать что-то вроде этого:
String formatString = "there were {0} {0,choice,0#objects|1#object|1<objects}";
MessageFormat fmt = new MessageFormat(formatString);
fmt.format(new Object[] { new Long(numberOfObjects) });
Ответ 3
Новые возможности JDK
Приведенные ниже инструкции доступны начиная с Java 12+.
Шаблоны строк начиная с Java 21 (в качестве первого предварительного просмотра)
Представлен как JEP-460 (предварительный просмотр) в Java 21 и более поздних версиях как JEP-459 (Второй предварительный просмотр) в Java 22. API не является окончательным, и эта часть ответа может быть изменена.
Это усовершенствование предоставляет процессоры шаблонов для выполнения интерполяции строк.
STR
статически импортируется неявно и немедленно интерполируется:int x = 10;
int y = 20;
// results in "10 + 20 = 30"
String result = STR."\{x} + \{y} = \{x + y}";RAW
статический импорт должен быть выполнен явно, а интерполяция отменена:int x = 10;
int y = 20;
StringTemplate st = RAW."\{x} + \{y} = \{x + y}";
...
// results in "10 + 20 = 30"
String result = STR.process(st);FMT
комбинируетсяSTR
с JavaFormatter
:int x = 10;
int y = 20;
// results in "10 + 20 = 30.00"
String result = FMT."%d\{x} + %d\{y} = %7.2f\{x + y}";
Альтернатива, начиная с Java 15
Начиная с Java 15, появился новый метод экземпляра, который называется String#formatted(Object... args)
.
Внутренняя реализация такая же, как String#format(String format, Object... args)
.
Форматирует, используя эту строку в качестве строки формата, и предоставленные аргументы.
String step1 = "one";
String step2 = "two";
// results in "Step one of two"
String string = "Step %s of %s".formatted(step1, step2);
Преимущество: Разница в том, что метод не является static
а шаблоном форматирования является сама строка, из которой создается новая на основе args
. Это позволяет chaining сначала создать сам формат.
Недостаток: в Locale
нет перегруженного метода, поэтому используется метод по умолчанию. Если вам нужно использовать пользовательский Locale
, вы должны придерживаться String#format(Locale l, String format, Object... args)
.
Старые функции JDK
Приведенные ниже рекомендации были хорошо известны до появления Java 11, но остаются актуальными до сегодняшнего дня.
String#format
Наиболее распространенным способом форматирования строки является использование этого статического метода, который давно доступен, начиная с Java 5, и имеет два перегруженных метода:
Метод прост в использовании, а format
шаблон определяется базовым средством форматирования.
String step1 = "one";
String step2 = "two";
// results in "Step one of two"
String string = String.format("Step %s of %s", step1, step2);
Вы можете передать Locale
для соблюдения языковых и региональных спецификаций. Обратитесь к этому ответу для получения дополнительной информации: https://javalang.ru/a/6431949/3764965 (заслуги Мартина Тернуолла).
MessageFormat
Класс MessageFormat
доступен с первой версии Java и подходит для интернационализации. В простейшей форме существует статический метод форматирования:
String step1 = "one";
String step2 = "two";
// results in "Step one of two"
String string = MessageFormat.format("Step {0} of {1}", step1, step2);
Помните, что MessageFormat
следует определенному шаблону, отличному от String#format
, обратитесь к его JavaDoc для получения более подробной информации: MessageFormat - patterns.
Можно использовать Locale
, однако необходимо создать экземпляр объекта класса и передать его конструктору, поскольку статический метод, приведенный выше, использует конструктор по умолчанию с языковым стандартом по умолчанию. Обратитесь к этому ответу для получения дополнительной информации: https://javalang.ru/a/6432100/3764965 (заслуги ataylor).
StringBuilder и конкатенация строк
Они хорошо известны и описаны где-либо еще.
Решения, отличные от JDK
Существует множество способов форматирования строк с использованием внешних библиотек. Они практически не приносят пользы, если библиотеки импортируются исключительно для форматирования строк. Несколько примеров:
- Apache Commons:
StringSubstitutor
, примеры в его JavaDoc. - Cactoos:
FormattedText
, примеры здесь. - Интересно, что Guava не планирует добавлять функции форматирования или создания шаблонов: #1142.
- ... и другие пользовательские реализации.
Не стесняйтесь добавлять больше, однако я не нахожу причин для дальнейшего расширения этого раздела.
Ответ 4
Если вы решите не использовать String.format , другим вариантом будет бинарный оператор +
String str = "Step " + a + " of " + b;
Это эквивалентно
new StringBuilder("Step ").append(String.valueOf(1)).append(" of ").append(String.valueOf(2));
Что бы вы ни использовали, выбирайте сами. StringBuilder быстрее, но разница в скорости незначительна. Я предпочитаю использовать +
оператор (который выполняет a) StringBuilder.append(String.valueOf(X)))
и считаю, что его легче читать.