Printf: примеры (JAVA)
printf(String format, Object... args): PrintStreamОбщее описание метода printf в Java
Метод printf присутствует в классах java.io.PrintStream (например, System.out) и java.io.PrintWriter, а также аналогом является метод format. Сигнатуры основных вариантов:
PrintStream printf(String format, Object... args)PrintStream printf(Locale l, String format, Object... args)PrintWriter printf(String format, Object... args)PrintWriter printf(Locale l, String format, Object... args)- Схожая функция:
String.format(String format, Object... args)- возвращает отформатированную строку.
Все варианты возвращают тот же поток/писатель (для методов в PrintStream/PrintWriter), что позволяет делать цепочки вызовов. Метод использует синтаксис форматной строки, совместимый с классом java.util.Formatter. В случае несоответствия типов или некорректной строки форматирования генерируется одно из исключений семейства IllegalFormatException.
Синтаксис спецификатора формата (общая форма):
%[argument_index$][flags][width][.precision]conversion
Ключевые части:
argument_index$- позиционный индекс аргумента (начиная с 1), например%2$s.flags- набор флагов:-(выровнять влево),+(всегда показывать знак),0(подставлять нули),,(группировка тысяч),((отображать отрицательные в скобках),<(повтор последнего аргумента).width- минимальная ширина поля (целое число)..precision- точность: для плавающей точки число знаков после запятой, для строк - максимальная длина.conversion- тип преобразования:b,B(boolean),c,C(char),d(десятичное целое),o(восьмеричное),x,X(шестнадцатеричное),e,E/f/g,G(числа с плавающей точкой),h,H(hashCode),s,S(строка),t,T(дата/время),%(символ процента),n(перевод строки).
Особенности и поведение:
- Форматирование с локалью: вариант с
Localeвлияет на разделитель дробной части и символ группировки. printfвPrintStreamвозвращает сам поток, поэтому можно писатьSystem.out.printf(...).printf(...).- Для получения строкового результата применяется
String.formatили объектjava.util.Formatter. - Некорректные сочетания спецификатора и типа аргумента приводят к
IllegalFormatConversionExceptionили другим подклассамIllegalFormatException.
Короткие примеры использования
Ниже представлены небольшие примеры с кодом и результатами.
Пример 1 - базовая подстановка и числовые спецификаторы
System.out.printf("Name: %s, Age: %d, Score: %.2f\n", "Ivan", 30, 95.678);
Name: Ivan, Age: 30, Score: 95.68
Пример 2 - флаги выравнивания и заполнения
System.out.printf("|%10s|%-10s|%010d|\n", "R", "L", 123);
| R|L |0000000123|
Пример 3 - группировка и знак
System.out.printf(Locale.US, "%+,d\n", 1234567);
+1,234,567
Пример 4 - позиционные аргументы и повтор использования
System.out.printf("First: %1$s, Second: %2$s, Again first: %1$s\n", "A", "B");
First: A, Second: B, Again first: A
Пример 5 - дата и время
java.util.Date now = new java.util.Date();
System.out.printf("Date: %tF %tT\n", now, now);
Date: 2026-04-22 14:35:00
Пример 6 - возвращаемое значение (цепочки)
System.out.printf("%s", "Hi").printf(" %d\n", 2026);
Hi 2026
Похожие средства в Java
В экосистеме Java присутствует несколько близких по назначению средств:
String.format- возвращает строку. Предпочтителен при необходимости получить результат какString, а не сразу выводить.Formatter- более гибкий инструмент для форматирования в разные Appendable (строки, файлы, буферы). Подходит при повторном использовании одного форматтера.MessageFormat- предназначен для локализованных сообщений; полезен при подготовке сообщений с параметрами и переносом в ресурсы.StringBuilder+ явная конкатенация - эффективен в простых случаях без сложного форматирования.
Выбор зависит от цели: вывод на консоль - printf или format, получение строки - String.format, сложные локализованные сообщения - MessageFormat, многократное форматирование в одном объекте - Formatter.
Аналоги в других языках и их отличия
Краткий обзор соответствий и особенностей в популярных языках с примерами.
PHP
printf("Name: %s, Score: %.2f\n", "Ivan", 95.678);
$s = sprintf("%d/%02d", 5, 3);
Name: Ivan, Score: 95.68 $s = "5/03"
Отличие: в PHP printf выводит, sprintf возвращает строку; синтаксис близок к C.
JavaScript (Node.js)
const util = require('util');
console.log(util.format('Num: %d, Str: %s', 42, 'hi'));
Num: 42, Str: hi
В браузерном JS встроенной printf-поддержки нет; template literals и Intl чаще используются.
Python
print("Name: %s, Price: %.2f" % ("Book", 12.5))
print("{:.2f}".format(3.14159))
print(f"{3.14159:.2f}")
Name: Book, Price: 12.50 3.14 3.14
В Python доступны три стиля: %-оператор, str.format и f-строки. f-строки наиболее читаемы и производительны в современных версиях.
C#
Console.WriteLine("Name: {0}, Age: {1}", "Ivan", 30);
var s = string.Format("{0:0.00}", 3.14159);
Name: Ivan, Age: 30 s = "3.14"
Отличие: C# использует позиционные плейсхолдеры в фигурных скобках и форматные строки .NET.
Go
fmt.Printf("Name: %s, Value: %.2f\n", "X", 1.234)
fmt.Sprintf("%d", 10)
Name: X, Value: 1.23 "10"
Go использует пакет fmt с синтаксисом, близким к C/Java.
Kotlin
println(String.format("%.2f", 2.71828))
System.out.printf("%s %d\n", "K", 1)
2.72 K 1
Kotlin использует те же механизмы, что и Java, плюс собственные string templates.
Lua
print(string.format("%s: %d", "X", 10))
X: 10
В Lua форматирование аналогично C, но без локализации и сложных флагов Java.
SQL (PostgreSQL)
SELECT format('Total: %s', 12345.67);
-- или в PL/pgSQL: RAISE NOTICE 'Value: %s', var;
Total: 12345.67
В SQL форматирование встроено в СУБД функционально, но применяется в контексте запроса/уведомлений.
Типичные ошибки при использовании
Ниже - распространённые ошибки с пояснениями и примерами.
1. Несоответствие типа и конверсии
System.out.printf("Number: %d\n", 3.14);
Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.Double
at java.base/java.util.Formatter.checkNumeric(Formatter.java:2720)
...
Причина: спецификатор %d ожидает целое число, а передан Double.
2. Отсутствие аргумента для спецификатора
System.out.printf("%s %s\n", "one");
Exception in thread "main" java.util.MissingFormatArgumentException: Format specifier '%s'
at java.base/java.util.Formatter.format(Formatter.java:2529)
...
3. Некорректный символ конверсии
System.out.printf("Value: %q\n", 10);
Exception in thread "main" java.util.UnknownFormatConversionException: Conversion = 'q'
at java.base/java.util.Formatter.checkText(Formatter.java:2703)
...
4. Неправильное использование флагов
System.out.printf("%+s\n", "text");
Exception in thread "main" java.util.FormatFlagsConversionMismatchException: Flags = '+' Conversion = s
at java.base/java.util.Formatter.failConversion(Formatter.java:3012)
...
Рекомендация при отладке: внимательно сверять спецификатор с типом аргумента и тестировать на граничных значениях.
Изменения и эволюция функции
Ключевые моменты истории и изменений:
- Механизм форматирования введён в Java 5 вместе с классом
Formatterи методамиprintf/format. - В последующих версиях в основном проводились исправления ошибок и улучшение поддержки локалей и юникода. Существенных синтаксических изменений в спецификаторах не происходило.
- Новые типы данных (например, java.time) получили улучшенную совместимость с форматированием на более поздних версиях Java, но общая модель осталась совместимой назад.
Поэтому при переходе между современными версиями Java код с использованием printf обычно остаётся работоспособным, если не используются баг-ориентированные обходы.
Расширенные и нестандартные примеры
Подробные примеры с пояснениями.
Табличный вывод с выравниванием и повторным использованием аргументов
String[] names = {"Alice", "Bob", "Christine"};
int[] vals = {5, 1234, -42};
System.out.printf("%1$-10s | %2$10s | %3$10s\n", "Name", "Value", "Signed");
for (int i = 0; i < names.length; i++) {
System.out.printf("%1$-10s | %2$,10d | %3$(10d\n", names[i], vals[i], vals[i]);
}
// Корректная версия с двумя форматами для числа
for (int i = 0; i < names.length; i++) {
System.out.printf("%1$-10s | %2$,10d | %3$(10d)\n", names[i], vals[i], vals[i]);
}
Name | Value | Signed Alice | 5 | 5 Bob | 1,234 | 1,234 Christine | -42 | (42)
Пояснение: используется -, группировка тысяч и флаг ( для отображения отрицательных в скобках.
Форматирование BigDecimal, управление точностью
java.math.BigDecimal bd = new java.math.BigDecimal("12345.6789");
System.out.printf(Locale.US, "Amount: %,.2f\n", bd);
Amount: 12,345.68
BigDecimal поддерживается как число с плавающей точкой при использовании %f и корректно округляется по заданной точности.
Дата/время: составные спецификаторы
java.util.Date d = new java.util.Date();
// Полный формат даты и времени
System.out.printf("%tF %tT\n", d, d);
// Частичные компоненты
System.out.printf("Day: %1$td, Month: %1$tm, Year: %1$tY\n", d);
// Использование положения аргумента для повторного вывода
System.out.printf("Start: %1$tT; End: %1$tT\n", d);
2026-04-22 14:35:00 Day: 22, Month: 04, Year: 2026 Start: 14:35:00; End: 14:35:00
Пояснение: спецификатор t работает с объектами Date, Calendar или миллисекундами.
Форматирование в файл через Formatter
try (java.util.Formatter f = new java.util.Formatter(new java.io.File("out.txt"), java.util.Locale.US)) {
f.format("Id: %03d, Price: %,.2f\n", 7, 1234567.89);
}
// Содержимое out.txt: Id: 007, Price: 1,234,567.89
(файл out.txt содержит строку) Id: 007, Price: 1,234,567.89
Пояснение: Formatter может писать прямо в файл или любой Appendable.
Повторное использование аргумента с флагом <
System.out.printf("Coordinates: (%f, %
Coordinates: (1.234500, 1.234500)
Флаг < указывает повторно применять предыдущий аргумент.
Безопасность: формирование SQL-запросов
// Небезопасно: уязвимость SQL-инъекции
String q = String.format("SELECT * FROM users WHERE name = '%s'", userInput);
// Рекомендуется использовать PreparedStatement вместо форматирования
(пример показан как предупреждение, результат зависит от userInput)
Пояснение: форматирование строк для SQL может привести к уязвимостям; использовать параметры PreparedStatement.