BackendBench
Coffee

Unravel โ€บ Java concepts โ€บ Strings and text

Java language

Formatting text and numbers

String.format("%s has %d items (%.2f%%)", name, n, pct) builds text from a template with placeholders.

Learn these first

At a glance

Mental model

A mail-merge letter: the template has gaps ("Dear %s"), and the program fills each gap with a value and the right formatting.

What happens, in order
  1. 1Placeholders: %s text, %d whole number, %f decimal, %.2f two decimals, %n newline, %x hex, %,d with thousand separators, %5d padded to width 5, %-10s left aligned, %% a literal percent sign
  2. 2printf is System.out.print(String.format(...)); "...".formatted(args) (Java 15) is the same on a string
  3. 3Format uses the default locale: in Germany %.2f prints 3,14Pass a Locale (String.format(Locale.US, ...)) when the output is for a file, JSON or another machine.
  4. 4NumberFormat.getCurrencyInstance(Locale.US).format(12.5) gives $12.50; DecimalFormat("#,##0.00") gives control of the pattern
Remember
Watch out
%d with a double, or %s expected and a missing argumentDepending on the default locale for machine-readable outputSharing a DecimalFormat between threads
Example (highlighted lines explain it)
import java.util.Locale;public class Receipt {  static String line(String item, int qty, double price) {    return String.format(Locale.US, "%-12s x%2d %8.2f", item, qty, price * qty);  }  static void print(String name, int count) {    System.out.printf("%s has %,d items%n", name, count);  }}
  1. line 4 uses format, the core of Formatting text and numbers
  2. line 7 uses printf, the core of Formatting text and numbers
Read the full explanation (about 1 min)

String.format("%s has %d items (%.2f%%)", name, n, pct) builds text from a template with placeholders. DecimalFormat and NumberFormat format numbers and currency for a locale.

A mental model

A mail-merge letter: the template has gaps ("Dear %s"), and the program fills each gap with a value and the right formatting.

How it works

Placeholders: %s text, %d whole number, %f decimal, %.2f two decimals, %n newline, %x hex, %,d with thousand separators, %5d padded to width 5, %-10s left aligned, %% a literal percent sign.

printf is System.out.print(String.format(...)); "...".formatted(args) (Java 15) is the same on a string.

Format uses the default locale: in Germany %.2f prints 3,14. Pass a Locale (String.format(Locale.US, ...)) when the output is for a file, JSON or another machine.

NumberFormat.getCurrencyInstance(Locale.US).format(12.5) gives $12.50; DecimalFormat("#,##0.00") gives control of the pattern.

Going deeper

A wrong placeholder type is a run-time error (IllegalFormatConversionException, e.g. %d with a double) and too few arguments gives MissingFormatArgumentException. The compiler does not check.

Never format money with double; use BigDecimal and format at the edge. NumberFormat and DecimalFormat are not thread safe: do not share one instance in a static field.

In logging, use the {} placeholders of SLF4J instead of String.format; they skip the work if the level is off.

Under the hood

String.format parses the template with a regular expression every call, which makes it slow in hot loops. A Formatter object writes into an Appendable and can be reused for many lines.

Common mistakes

  • %d with a double, or %s expected and a missing argument.
  • Depending on the default locale for machine-readable output.
  • Sharing a DecimalFormat between threads.

How Unravel recognises it

When you paste code, Unravel looks for these signs of formatting text and numbers. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is Formatting text and numbers?

String.format("%s has %d items (%.2f%%)", name, n, pct) builds text from a template with placeholders. DecimalFormat and NumberFormat format numbers and currency for a locale.

What are the most common mistakes with Formatting text and numbers?

%d with a double, or %s expected and a missing argument. Depending on the default locale for machine-readable output. Sharing a DecimalFormat between threads.

How can I see Formatting text and numbers in real code?

Paste your own Java into Unravel and it will point out where formatting text and numbers appears, explain how it works at the detail level you choose, and draw the flow of the code around it.