printf() это метод класса java.io.PrintStream, который печатает текст по шаблону: в строку формата подставляются значения аргументов, а спецификаторы вида %s, %d, %.2f задают, как именно их показать. Вызывают его как System.out.printf(формат, аргументы). Это удобнее склейки строк плюсами: ширина колонок, число знаков после запятой и выравнивание задаются прямо в шаблоне.

Кратко

  • Синтаксис: System.out.printf("Привет, %s!%n", "Мир"). Первый аргумент это строка формата, дальше идут значения по порядку.
  • Основные спецификаторы: %s строка, %d целое, %f дробное, %e научная нотация, %c символ, %b логическое значение.
  • Между % и буквой ставят ширину и точность: %10s дополнит строку пробелами слева до 10 символов, %-10s выровняет по левому краю, %.2f оставит два знака после запятой.
  • Разделитель дробной части зависит от локали: в русской локали %.2f напечатает 3,14, а в Locale.US 3.14. Локаль можно задать первым аргументом: System.out.printf(Locale.US, "%.2f", 3.14159).
  • Перенос строки printf сам не добавляет: в конце пишут %n (системный перенос) или \n.
  • Несовместимые флаг и спецификатор дают FormatFlagsConversionMismatchException во время выполнения, а не при компиляции: например, %+s.
Метод printf() принадлежит стандартной библиотеке Java и играет важную роль в форматировании вывода. Эта статья предоставит новичкам полное понимание метода printf() в Java, его назначения и эффективного использования.

Введение в функцию Java Printf

Работающая печатная машина в типографии: метафора форматированного вывода в JavaМетод printf() в Java (название расшифровывается как print formatted) используется для форматирования текста и переменных для вывода. Сами шаблоны вида %s или %d внутри строки формата называются спецификаторами формата. Этот инструмент можно использовать для создания информативных текстовых строк без использования конкатенации String или полагания на нестандартные символы, которые могут вызвать ошибки вывода. Заполнители заменяются фактическими значениями при печати строки в консоль. Метод printf() мощен, поскольку позволяет контролировать внешний вид текста, чисел и других типов данных в выводе. Метод printf() объявлен в классе PrintStream и имеет следующую сигнатуру:

public PrintStream printf(String format, Object... args)
Обратите внимание: метод не статический, его вызывают у готового потока вывода (System.out), а возвращает он сам поток, поэтому вызовы можно писать цепочкой. Есть и второй вариант, которому первым аргументом передают локаль: printf(Locale l, String format, Object... args). Функция Java printf принимает два аргумента:
  • Строка формата: Эта строка содержит специальные символы форматирования, которые сообщают функции printf, как форматировать вывод.
  • Переменное количество аргументов: Эти аргументы являются значениями, которые будут отформатированы и выведены.
Строка формата может содержать любую комбинацию литерального текста, символов форматирования и специальных символов. Символы форматирования сообщают функции printf, как форматировать вывод каждого аргумента. Вот простой пример использования функции printf:

System.out.printf("Привет, %s!\n", "Мир");
В этом примере строка формата содержит две части:
  • Литеральный текст "Привет, ": Этот текст будет выведен буквально.
  • Символ форматирования "%s": Этот символ говорит функции printf отформатировать следующий аргумент как строку.
  • Аргумент "Мир": Это значение, которое будет отформатировано и выведено как строка.
Вывод этого кода будет:
Привет, Мир!

Символы форматирования

Функция printf поддерживает множество символов форматирования, каждый из которых может использоваться для контроля внешнего вида вывода. Например, следующие символы форматирования можно использовать для форматирования самых популярных примитивных типов данных в Java:
  • %d: форматирует аргумент как целое число;
  • %f: форматирует аргумент как число с плавающей точкой;
  • %e: форматирует аргумент как экспоненциальное число с плавающей точкой;
  • %s: форматирует аргумент как String;
  • %c: форматирует аргумент как символ;
  • %b: форматирует аргумент как Boolean. Значение "true" выводится, если аргумент истинен, и значение "false" выводится, если аргумент ложен.
  • %n: печатает перенос строки, принятый в текущей операционной системе;
  • %%: печатает сам знак процента.
Два последних пункта стоит запомнить сразу: в отличие от println(), метод printf() перенос строки сам не добавляет, а знак процента в шаблоне нужно удваивать, иначе Java примет его за начало спецификатора:

System.out.printf("Скидка %d%%%n", 15); // Скидка 15%
System.out.printf("Первая строка%n");
System.out.printf("Вторая строка%n");
Вместо %n можно писать и \n: разница в том, что \n это всегда один символ перевода строки, а %n подставляет разделитель строк текущей системы (в Windows это пара символов).

Понимание форматирования

Форматирование является важнейшим аспектом любого языка программирования, поскольку оно определяет, как данные представляются пользователям. С методом Java printf форматирование становится проще и более гибким. Вы можете контролировать ширину полей, указывать количество десятичных знаков для чисел с плавающей точкой и выравнивать текст в соответствии с вашими требованиями.

Использование метода Java Printf

Рассмотрим несколько примеров. В первом мы собираемся отформатировать десятичное число пи.

public class PrintfExample1 {
    public static void main(String[] args) {
        double pi = 3.141592;
        int precision = 3;
        //пример printf 
        System.out.printf("Значение пи с %d десятичными знаками: %.3f", precision, pi);
    }
}
Вывод этой программы:
Значение пи с 3 десятичными знаками: 3,142
Здесь мы используем метод printf() для форматирования и отображения значения пи с определенным количеством десятичных знаков. Спецификатор формата %.3f указывает, что мы хотим отобразить число с плавающей точкой с тремя десятичными знаками. Обратите внимание на запятую в выводе: дробные числа форматируются по правилам текущей локали, а в русской локали разделителем служит именно запятая. Если нужна точка независимо от настроек системы, локаль передают первым аргументом:

System.out.printf(Locale.US, "Значение пи: %.3f%n", pi); // Значение пи: 3.142
Дальше в статье все выводы показаны для русской локали. Теперь рассмотрим другой пример Java printf, в котором мы выводим отформатированные строки и целые числа:

public class PrintfExample2 {
    public static void main(String[] args) {
        String name = "Алиса";
        int age = 15;
        //пример printf
        System.out.printf("Привет, меня зовут %s, и мне %d лет.", name, age);
    }
}
Вывод программы:
Привет, меня зовут Алиса, и мне 15 лет.
В этом примере мы используем метод printf() для форматирования и отображения сообщения, которое включает строковое и целочисленное значение. Спецификатор формата %s используется для строки, а %d используется для целого числа. Давайте углубимся в практический пример, чтобы понять, как работает метод printf(). Предположим, вы хотите отобразить имя, возраст и зарплату сотрудника. Вот как вы можете достичь этого, используя метод printf():

public class PrintfExample {
    public static void main(String[] args) {
        String name = "Иван";
        int age = 30;
        double salary = 50000.50;
        //пример printf
        System.out.printf("Имя: %s, Возраст: %d, Зарплата: %.2f", name, age, salary);
    }
}
Вывод:
Имя: Иван, Возраст: 30, Зарплата: 50000,50
В этом примере спецификаторы формата %s, %d и %.2f используются для обозначения строковых, целочисленных значений и значений с плавающей точкой соответственно. Значения name, age и salary предоставляются как аргументы после строки формата. Теперь попробуем использовать метод printf() для форматирования и отображения логического значения:

public class PrintfExample3 {
    public static void main(String[] args) {
        boolean isJavaFun = true;
        //пример printf
        System.out.printf("Java интересна? %b", isJavaFun);
    }
}
Вывод:
Java интересна? true
В этом примере мы используем метод printf() для форматирования и отображения того, интересна ли Java или нет. Спецификатор формата %b используется для логических значений. Эти примеры демонстрируют, как метод printf() может использоваться для форматирования и отображения различных типов данных в Java. Спецификаторы формата помогают контролировать выравнивание, ширину, точность и другие аспекты форматирования вывода.

Продвинутые техники форматирования

Научная нотация необходима при работе с очень большими или очень малыми числами. Метод printf поддерживает научную нотацию, используя спецификаторы формата %e или %E.

Пример: научная нотация

public class ScientificNotationExample {
    public static void main(String[] args) {
        double largeNumber = 123456789.12345;
        double smallNumber = 0.000012345;

        System.out.printf("Большое число в научной нотации: %e\n", largeNumber);
        System.out.printf("Малое число в научной нотации: %E\n", smallNumber);
    }
}

Вывод:

Большое число в научной нотации: 1,234568e+08 Малое число в научной нотации: 1,234500E-05

Здесь спецификаторы %e и %E представляют числа в научной нотации, где e или E указывает степень 10.

Обработка FormatFlagsConversionMismatchException

При использовании printf несовпадающие флаги формата и типы преобразования могут привести к FormatFlagsConversionMismatchException. Это исключение возникает, когда используется неподдерживаемая комбинация флагов и спецификаторов, например, использование '+' с %s (строкой).

Пример: несовместимый флаг

import java.util.FormatFlagsConversionMismatchException;

public class FormatExceptionExample {
    public static void main(String[] args) {
        try {
            System.out.printf("Неверный формат: %+s\n", "текст");
        } catch (FormatFlagsConversionMismatchException e) {
            System.out.println("Исключение поймано: " + e.getMessage());
        }
    }
}

Вывод:

Исключение поймано: Conversion = s, Flags = +

Чтобы избежать этого исключения, убедитесь, что флаги и спецификаторы формата совместимы. Обратитесь к документации Java для получения информации о разрешенных комбинациях.

Использование ширины, точности и флагов формата в продвинутом форматировании

Метод printf предоставляет опции для контроля ширины, точности и выравнивания отформатированных выводов, что делает его идеальным для создания структурированных таблиц или визуально привлекательных выводов.

1. Контроль ширины

Спецификатор ширины обеспечивает, что вывод занимает фиксированное количество символов. Если значение короче указанной ширины, оно дополняется пробелами.

System.out.printf("|%10s|\n", "Java"); // Выравнивание по правому краю
System.out.printf("|%-10s|\n", "Java"); // Выравнивание по левому краю

Вывод:

| Java| |Java |

2. Контроль точности

Точность используется для контроля количества десятичных знаков для значений с плавающей точкой или максимальной длины символов для строк.

System.out.printf("%.2f\n", 123.4567); // Ограничивает до 2 десятичных знаков
System.out.printf("%.5s\n", "JavaProgramming"); // Ограничивает до 5 символов

Вывод:

123,46 JavaP

3. Комбинирование ширины и точности

Вы можете комбинировать ширину и точность для более сложного форматирования. Например:

System.out.printf("|%10.2f|\n", 123.4567); // Выравнивание по правому краю с 2 десятичными знаками
System.out.printf("|%-10.2f|\n", 123.4567); // Выравнивание по левому краю с 2 десятичными знаками

Вывод:

| 123,46| |123,46 |

Преимущества использования Printf

Метод Java printf() предлагает несколько преимуществ, включая:
  • Улучшенный контроль над форматированием текста.
  • Упрощенное выравнивание и точность для числовых значений.
  • Повышенная читаемость кода, особенно для сложного форматирования.
  • Последовательное форматирование в различных операторах вывода.

Шпаргалка: спецификаторы, ширина и флаги

Соберем все разобранное в одну таблицу:
Запись Что делает Пример вызова Вывод
%s подставляет строку (для любого объекта вызовет toString()) printf("%s", "Мир") Мир
%d целое число printf("%d", 42) 42
%f дробное число, по умолчанию 6 знаков после запятой printf("%f", 3.14) 3,140000
%.2f дробное число с заданной точностью printf("%.2f", 3.14159) 3,14
%e и %E научная нотация, строчная и прописная printf("%e", 123456789.0) 1,234568e+08
%c один символ printf("%c", 'A') A
%b логическое значение printf("%b", true) true
%10s ширина поля: дополняет пробелами слева printf("|%10s|", "Java") | Java|
%-10s ширина поля с выравниванием по левому краю printf("|%-10s|", "Java") |Java |
%,d группировка разрядов по правилам локали printf(Locale.US, "%,d", 1000000) 1,000,000
%n перенос строки, зависящий от операционной системы printf("строка%n") перевод строки
%% печатает сам знак процента printf("100%%") 100%

Заключение

Метод printf() в Java является универсальным инструментом для форматирования вывода в удобном для пользователя виде. Понимая его использование и спецификаторы формата, разработчики могут эффективно представлять данные пользователям с точностью и ясностью. Независимо от того, отображаете ли вы простые сообщения или сложные данные, метод printf() дает вам возможность создавать визуально привлекательный и информативный вывод.

Вопросы и ответы

Чем printf отличается от println?

println() печатает готовую строку и переводит курсор на новую строку, а printf() принимает шаблон и подставляет в него значения, управляя их видом: числом знаков после запятой, шириной колонки, выравниванием. Перенос строки printf() сам не делает, его добавляют через %n или \n. Если форматирование не нужно, println() короче и понятнее.

Чем %n отличается от \n?

\n это всегда один символ перевода строки (код 10), а %n это спецификатор, который подставляет разделитель строк текущей операционной системы: в Linux и macOS тот же \n, в Windows пару \r\n. В файлах и протоколах, которые читают другие программы, обычно берут %n, если важна совместимость с системой, и \n, когда формат строго фиксирован.

Почему printf печатает 3,14 вместо 3.14?

Потому что дробные числа форматируются по правилам текущей локали, а в русской локали разделителем целой и дробной части служит запятая. Чтобы получить точку независимо от настроек системы, локаль передают первым аргументом: System.out.printf(Locale.US, "%.2f%n", 3.14159). Тот же прием нужен, когда число уходит в CSV, JSON или SQL, где точка обязательна.

Чем printf отличается от String.format?

Ничем, кроме результата: printf() сразу печатает текст в поток вывода, а String.format() возвращает готовую строку, которую можно сохранить, передать дальше или записать в файл. Набор спецификаторов и правила локали у них одинаковые, потому что внутри работает один и тот же класс java.util.Formatter. С Java 15 есть и метод экземпляра: "%.2f".formatted(3.14159).

Как выровнять данные в колонки?

Задать ширину поля между % и буквой спецификатора: %15s выровняет строку по правому краю в поле из 15 символов, %-15s по левому. Числа комбинируют ширину с точностью: %10.2f. Так из нескольких вызовов printf() собирают таблицу, где колонки не разъезжаются, а заголовок печатают тем же шаблоном, что и строки данных.

Какие ошибки чаще всего возникают при работе с printf?

Три типичные: количество аргументов не совпадает с числом спецификаторов (MissingFormatArgumentException), тип аргумента не подходит спецификатору, например %d для дробного числа (IllegalFormatConversionException), и несовместимый флаг, например %+s (FormatFlagsConversionMismatchException). Все они возникают во время выполнения, компилятор их не ловит, поэтому строку формата стоит проверять на реальных данных. Читайте также: