String Formatting in Java: String.format(), printf() and Formatter - Quiz

Total: 5 questions

1. 

What is the difference between String.format(), formatted(), System.out.printf() and the Formatter class in Java?

They all understand the same template syntax and use java.util.Formatter under the hood. The difference is where the result goes:

  • String.format(template, args...) (Java 5) returns a new string — Java's sprintf;
  • "template".formatted(args...) (Java 15) does the same but is shorter and works nicely with text blocks; it has no Locale overload and always uses the default locale;
  • System.out.printf() and System.out.format() are two names for the same PrintStream method and print straight to the console; they add no line break on their own, so you write %n in the template;
  • Formatter accumulates text from several format() calls and can write into a StringBuilder, a file or a stream.
String a = String.format("%s: %d", "Anna", 5);
String b = "%s: %d".formatted("Anna", 5);
System.out.printf("%s: %d%n", "Anna", 5);

StringBuilder sb = new StringBuilder();
Formatter f = new Formatter(sb, Locale.US);
f.format("%-8s%6.2f%n", "Tea", 3.5);
2. 

What parts does a Java format specifier consist of, and which of them are required?

The general form is %[argument_index$][flags][width][.precision]conversion. Only the % sign and the conversion character (d, s, f, x…) are required; everything else is optional:

  • argument_index$ — the argument number starting at 1 (%2$s); %<s reuses the argument of the previous specifier;
  • flags — alignment, sign, leading zeros, grouping separators (-, +, 0, ,, (, #, space);
  • width — the minimum field width: a shorter value is padded with spaces, a longer one is printed in full;
  • .precision — digits after the decimal point for floating-point numbers (rounded with HALF_UP), maximum length for strings.
String.format(Locale.US, "[%8.2f]", 1000.0 / 3.0); // [  333.33]
String.format("[%.3s]", "Formatter");               // [For]
String.format("[%3s]", "Formatter");                // [Formatter]

Uppercase variants (%S, %X, %B…) convert the result to upper case; %d, %f and %o have no uppercase forms.

3. 

How do you format a date with String.format(), and why does the template "%tm/%td/%tY" with a single date fail?

Dates use the %t (or %T) specifier with a suffix: %tY is the year, %tm the month, %td the day, %tB the month name, %tF the ISO date. The argument can be a LocalDate, LocalDateTime, Date, Calendar or long.

Every specifier without an index takes the next argument, so "%tm/%td/%tY" with one date expects three arguments and throws MissingFormatArgumentException. Refer to the same argument with the %1$ index:

LocalDate date = LocalDate.of(2026, 10, 16);
String.format("%tF", date);                             // 2026-10-16
String.format("%1$tm/%1$td/%1$tY", date);               // 10/16/2026
String.format(Locale.US, "%1$tB %1$te, %1$tY", date);   // October 16, 2026
String.format("%tm/%td/%tY", date);                     // MissingFormatArgumentException

For complex date patterns, modern code usually reaches for java.time.format.DateTimeFormatter.

4. 

What are the most common mistakes in String.format() templates, and which exceptions do they throw?

The compiler does not check format strings: mistakes surface only at runtime as unchecked exceptions, subclasses of IllegalFormatException (which extends IllegalArgumentException).

String.format("%d", 3.5);           // IllegalFormatConversionException: d != java.lang.Double
String.format("%s and %s", "A");    // MissingFormatArgumentException: Format specifier '%s'
String.format("%-05d", 7);          // IllegalFormatFlagsException: Flags = '-0'
String.format("%i", 7);             // UnknownFormatConversionException: Conversion = 'i'
String.format("Save 50%");          // UnknownFormatConversionException: Conversion = '%', use 50%%
String.format("%s", "a", "b");      // no exception: "a", the extra argument is ignored
String.format("%d", (Integer) null); // no exception: "null"

The - or 0 flag without a width gives MissingFormatWidthException. Java has no %i or %u from C — integers are printed only with %d.

5. 

How do DecimalFormat and MessageFormat differ from String.format(), and what are the MessageFormat pitfalls?

Both classes live in the java.text package. DecimalFormat formats a number by a pattern such as #,##0.00, and MessageFormat inserts arguments by number in curly braces {0}, {1} instead of % specifiers — the approach used in UI localization bundles.

DecimalFormat df = new DecimalFormat("#,##0.00",
        DecimalFormatSymbols.getInstance(Locale.US));
df.format(1234567.891); // 1,234,567.89

MessageFormat.format("File {0} contains {1} lines", "data.txt", 1500);
// File data.txt contains 1,500 lines
MessageFormat.format("File {0} contains {1,number,#} lines", "data.txt", 1500);
// File data.txt contains 1500 lines

MessageFormat pitfalls: numbers in {1} are formatted with the locale's grouping separators (1500 → 1,500; output shown for Locale.US), and {1,number,#} prints them without separators. A single quote in the pattern is an escape character, so an apostrophe has to be doubled: "Don''t" prints Don't.

Page 1 of 1