skip to content

Explain printf/format formatted output in Java: how format specifiers work and what %s, %d, %f, %n, and width/precision flags do.

level: middleimportance: should knowfreq 58%

answer

  1. %[index$][flags][width][.precision]conversion
  2. %s string, %d int, %f float, %b bool, %% literal percent
  3. %n = portable newline (not \\n)
  4. width=min size (pad), precision=decimals or max chars
  5. flags: - left, 0 zero-pad, , group, + sign

basics

~20 s

printf/format prints text using a format string with placeholders called format specifiers. Each starts with % - for example %s for a string, %d for an integer, %f for a floating-point number, and %n for a platform-correct newline. You can add width and precision, like %8.2f for a number padded to 8 wide with 2 decimals.

solid answer

~40 s

Java's printf-style output (on Console, PrintStream/System.out, PrintWriter, or via String.format / Formatter) takes a format string with format specifiers and a varargs list of arguments. A specifier has the form %[argument_index$][flags][width][.precision]conversion. Common conversions: %s (any object via toString or Formattable), %d (decimal integer), %f (decimal float), %e (scientific), %x (hex), %b (boolean), %c (char), %% (literal percent), and %n (platform line separator - prefer it over \n). Width sets a minimum field size with right-justification by default; the '-' flag left-justifies; '0' zero-pads; ',' groups thousands; '+' shows a sign. Precision means decimal places for %f and max length for %s. Mismatched types throw IllegalFormatException, and %d with a decimal value throws too. Argument indexing (%1$s) lets one argument be reused. printf returns the stream/console for chaining.

code

java · 11 lines
java
String name = "Ada";
int score = 7;
double pct = 0.8423;

// %-12s : left-justified in 12 cols; %3d : right in 3; %6.2f%% : 2 decimals + literal %
System.out.printf("%-12s score=%3d (%6.2f%%)%n", name, score, pct * 100);
// Ada          score=  7 ( 84.23%)

// Argument index reuse and thousands grouping
System.out.printf("%1$s owes %2$,d cents; thanks %1$s!%n", name, 1234567);
// Ada owes 1,234,567 cents; thanks Ada!

go deeper

for a junior

Recognizes %s/%d/%f and %n and can produce simple formatted lines.

for a middle

Explains the full specifier structure, width vs precision, common flags, and that type mismatches throw at runtime.

for a senior

Discusses locale sensitivity, argument indexing, the shared Formatter engine behind printf/String.format, and when to choose each.

for a principal

Guides on i18n-safe formatting (explicit Locale), performance of repeated formatting vs precompiled approaches, and conventions for log/output consistency across a codebase.

## What "formatted output" means Instead of gluing strings together with `+`, Java lets you write a **template** (the *format string*) with **placeholders**, then supply the values separately. The method scans the template and substitutes each placeholder with the next value, applying formatting rules. This is the same idea as C's `printf`. The methods that do this: - `console.printf(fmt, args)` and `console.format(fmt, args)` (identical) - `System.out.printf(...)` (PrintStream) and PrintWriter.printf - `String.format(fmt, args)` - returns the formatted String instead of printing - `java.util.Formatter` - the engine all of these use under the hood ## Anatomy of a format specifier A placeholder (called a **format specifier** or **conversion**) has this structure: ``` %[argument_index$][flags][width][.precision]conversion ``` Only the leading `%` and the trailing **conversion** letter are required. ### Conversions (the last letter - says *what kind* of value) - `%s` - string: calls the argument's `toString()` (or uses Formattable). Works for any object. - `%d` - decimal **integer** (byte/short/int/long/BigInteger). A non-integer like a `double` throws. - `%f` - decimal **floating-point** (float/double), default 6 decimal places. - `%e` / `%g` - scientific / general floating-point. - `%x` / `%o` - hexadecimal / octal integer. - `%b` - boolean ("true"/"false"; non-null non-boolean prints "true"). - `%c` - a single character. - `%%` - a literal percent sign (you cannot write a bare `%`). - `%n` - the **platform line separator** (`\n` on Unix, `\r\n` on Windows). Prefer `%n` over `\n` for portable newlines. ### width - minimum field size `%5d` means "at least 5 characters wide". If the value is shorter it is **padded with spaces**, **right-justified** by default. `%5d` with `42` -> `" 42"`. ### .precision - decimals or max length - For `%f`: number of digits after the decimal point. `%.2f` of `3.14159` -> `"3.14"` (it rounds). - For `%s`: the **maximum** number of characters. `%.3s` of `"hello"` -> `"hel"`. Combine them: `%8.2f` of `3.14159` -> `" 3.14"` (8 wide, 2 decimals, space-padded). ### flags - modify alignment/sign/padding (between % and width) - `-` left-justify: `%-5d` with `42` -> `"42 "`. - `0` zero-pad: `%05d` with `42` -> `"00042"`. - `,` group thousands by locale: `%,d` with `1000000` -> `"1,000,000"`. - `+` always show sign: `%+d` with `42` -> `"+42"`. - `(` put negatives in parentheses: `%(d` with `-42` -> `"(42)"`. - space: leading space for positive numbers. ### argument_index$ - reuse/reorder arguments `%1$s %1$s` prints the **first** argument twice. Useful for reordering in localized strings. ## Errors to know - Passing the wrong type for a conversion (e.g. a String to `%d`) throws **IllegalFormatConversionException**. - `%d` with a `double` throws (use `%f`). - Too few arguments throws **MissingFormatArgumentException**. These are unchecked (RuntimeException) and surface at runtime, so test your format strings. ## Locale Formatting is **locale-sensitive**: decimal separators and grouping follow the default Locale unless you use an overload that takes a `Locale`. This matters for `%f` and `%,d` across regions. ## Worked example ```java System.out.printf("%-10s %5d %8.2f%n", "apples", 42, 3.5); // -> "apples 42 3.50\n" ``` `%-10s` left-justifies "apples" in 10 columns; `%5d` right-justifies 42 in 5; `%8.2f` formats 3.5 as 3.50 in 8 columns; `%n` ends the line. ## How to derive the answer Read a specifier left to right: `%`, then optional index/flags/width/precision, then the conversion letter that names the type. Width = minimum size (pad), precision = decimals (for floats) or max chars (for strings), flags = how to pad/sign/align. `%n` = portable newline, `%%` = literal percent.

  • What's the difference between %n and \n?
    %n emits the platform-specific line separator (\n on Unix, \r\n on Windows), making output portable. \n is always a single line-feed regardless of OS. In format strings prefer %n.
  • How do you print a value with exactly two decimal places and thousands separators, like 1,234,567.89?
    Use %,.2f - the comma flag groups thousands and .2 sets two decimals: String.format("%,.2f", 1234567.89) -> "1,234,567.89" (separator depends on Locale).

saying these in an interview costs you the question

  • Using %d for a double (throws IllegalFormatConversionException)
  • Writing a bare % instead of %% for a literal percent
  • Assuming %n equals \n on all platforms (it's the OS line separator)
  • Thinking width truncates - it only pads; precision on %s truncates
  • Ignoring locale effects on decimal separators / grouping

context