Format Strings with String.format
`String.format` is Java's printf-style formatter for building human-readable strings without ad-hoc concatenation. This snippet covers the common conversions (`%s`, `%d`, `%.2f`, `%n`), padding and alignment for table layouts, and locale-aware vs locale-independent formatting. Reach for `String.format` for any output that mixes types or needs precise width control.
299 views
8
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String name = "Ada";
int level = 7;
double balance = 1234.5;
// %s string, %d integer, %f float, %n platform line separator
String msg = String.format("%s is level %d with balance %.2f%n", name, level, balance);
System.out.print(msg);
// printf is the same formatter going straight to stdout
System.out.printf("hex=%x bin=%s oct=%o%n", 255, Integer.toBinaryString(5), 8);
}
}The format string contains conversion specifiers introduced by %. %s is the most general, calling toString() on whatever you pass. %d requires an integer, %f a floating-point number with optional precision (%.2f for two decimals), and %n emits the platform-correct line separator (use it instead of \n for portable output). String.format returns a String; System.out.printf writes directly to stdout using the same syntax.
public class Main {
public static void main(String[] args) {
String[] names = {"Ada", "Linus", "Margaret"};
int[] scores = {72, 100, 88};
// %-10s left-aligns in width 10; %4d right-aligns in width 4
System.out.printf("%-10s %4s%n", "name", "pct");
System.out.println("---------- ----");
for (int i = 0; i < names.length; i++) {
System.out.printf("%-10s %4d%n", names[i], scores[i]);
}
}
}A width number after % reserves at least N characters for the value, padding with spaces if shorter. By default text is right-aligned; the - flag flips to left alignment, which is what you want for variable-width strings in a table. You can combine width with precision (%-10.5s left-aligns and truncates to 5 chars). Use this for log lines, CLI output, or anywhere a fixed-column layout makes scanning easier than CSV.
import java.util.Locale;
public class Main {
public static void main(String[] args) {
double pi = 3.14159;
// Default locale: may use ',' as the decimal separator (e.g. de-DE)
String german = String.format(Locale.GERMAN, "%.2f", pi);
String us = String.format(Locale.US, "%.2f", pi);
System.out.println("DE: " + german); // 3,14
System.out.println("US: " + us); // 3.14
// Locale.ROOT is the safe choice for machine-readable output
// (logs, file names, JSON-like text). Always pass it explicitly
// when the consumer is another program rather than a human.
String safe = String.format(Locale.ROOT, "price=%.2f", 1234.5);
System.out.println(safe); // price=1234.50
}
}Without an explicit Locale, String.format uses Locale.getDefault(Category.FORMAT), which means the same code can produce 1,5 on a German JVM and 1.5 on a US one. That is fine for human-facing UI but disastrous for logs, file names, or JSON: a Locale-sensitive number that a downstream parser cannot read. Always pass Locale.ROOT (or another explicit locale) for machine-consumed output. Number-heavy code that mixes both should standardise on Locale.ROOT and only switch to user locale at the rendering boundary.
