Printf: примеры (JAVA)

printf в Java: синтаксис и практические примеры
Раздел: Ввод-вывод (I/O) консольный
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 обычно остаётся работоспособным, если не используются баг-ориентированные обходы.

Расширенные и нестандартные примеры

Подробные примеры с пояснениями.

Табличный вывод с выравниванием и повторным использованием аргументов

Пример java
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
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
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

Пример java
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.

Повторное использование аргумента с флагом <

Пример java
System.out.printf("Coordinates: (%f, %
Coordinates: (1.234500, 1.234500)

Флаг < указывает повторно применять предыдущий аргумент.

Безопасность: формирование SQL-запросов

Пример java
// Небезопасно: уязвимость SQL-инъекции
String q = String.format("SELECT * FROM users WHERE name = '%s'", userInput);
// Рекомендуется использовать PreparedStatement вместо форматирования
(пример показан как предупреждение, результат зависит от userInput)

Пояснение: форматирование строк для SQL может привести к уязвимостям; использовать параметры PreparedStatement.

джава printf function comments

En
Printf Prints a formatted string to the console