Explain printf/format formatted output in Java: how format specifiers work and what %s, %d, %f, %n, and width/precision flags do.
answer
- %[index$][flags][width][.precision]conversion
- %s string, %d int, %f float, %b bool, %% literal percent
- %n = portable newline (not \\n)
- width=min size (pad), precision=decimals or max chars
- flags: - left, 0 zero-pad, , group, + sign
basics
~20 sprintf/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 sJava'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 linesString 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
Recognizes %s/%d/%f and %n and can produce simple formatted lines.
Explains the full specifier structure, width vs precision, common flags, and that type mismatches throw at runtime.
Discusses locale sensitivity, argument indexing, the shared Formatter engine behind printf/String.format, and when to choose each.
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