Formatting Strings With Java
We all know String.format(...)
.
But there are other options. Java has multiple ways of formatting, aligning, padding, and justifying Strings.
Table of Contents
History of String Formatting
Programming languages have a long tradition of formatting Strings.
Over 60 years ago, Fortran
was released with the FORMAT
keyword:
The more commonly known C
-style format Strings, used by the printf
, and Java’s String.format
originated from BCPL
:
Java wasn’t incepted with String.format
.
It took eight years until the release of Java 1.5 for it to be included.
Before that, java.text.MessageFormat
was the way to bend Strings to your will.
Format Specifier
All format Strings start with %
and consist of multiple optional parts and the actual conversion specifier.
The general syntax can be split into three different groups:
- General, character, and numeric types
%[argument_index$][flags][width][.precision]conversion
- Date and times
%[argument_idnex$][flags][width][.precision]conversion
- Argumentless specifiers
%[flags][width]conversion
The conversion argument can also be separated into different groups:
Most conversions support lowercase and uppercase, differentiated by using the conversion specifier in lowercase or uppercase. For simplicity, only the lowercase version will be listed in the article.
If a null
argument is supplied, it’s converted to “null”.
General conversions
Examples:
Characters
Integrals
Examples:
Floating-point
Examples:
Date / time
Date and time format specifiers are prefixed with %t
, followed by the specific part.
Many of the conversions are locale-specific and default to the default locale of the JVM if no alternative is provided.
Other conversions
Flags
Flags can be used to modify the conversion:
Width
The absolute width of the output can specific, except for the line separator conversion:
Precision
The behaviour is dependent on the conversion type.
For general argument types, the precision is the number of resulting formatted characters.
The floating-point conversions (%a
, %e
, %f
) are restricting the number of digits after the decimal separator.
A special case is %g
, which will define the number of digits in the resulting magnitude after rounding.
For the other conversions (character, integral, date/time, and the percent and line separator conversions) specifying a precision is not applicable, and will throw an exception.
Argument index
The argument index indicates the position of the argument in the argument list, e.g., 1$
for the first, 2$
for the second, and so forth.
This way, we can use different format specifiers without changing the actual argument list.
If we want to reuse the previously used argument position, we can use <
(\u003c
) instead:
Formatting Options
java.lang.String.format
The most simple formatting options available are these two static methods:
Actually, these are just delegating the work to java.util.Formatter
:
If no java.util.Locale
is provided, the JVM default is used.
java.util.Formatter
The java.util.Formatter
class is the actual interpreter for printf
format specifiers and is doing all the heavy lifting in our format needs.
Internally it all comes down to the java.lang.Appendable
interface and a java.util.Locale
.
With its multiple constructors, java.util.Formatter
can have a different target for the formatted result:
Both format
methods we know from java.lang.String
are present, but instead of returning a new String, the Formatter
instance is returned.
Depending on the backing, java.lang.Appendable
additional calls to flush()
and close()
.
System.out.printf
The method System.out.printf
uses a java.util.Formatter
internally, just like java.lang.String
.
The big difference is the calls are synchronized to the System.out
, which is a java.io.PrintStream
.
java.text.MessageFormat
We now have learned about the different ways to use printf
format specifiers.
But Java had a more natural-language-based way of formatting Strings.
Instead of a rather cryptic format String, simpler specifiers in curly braces are used:
{argument index , format type , style }
The argument index is mandatory. The format type and style are optional, but style can’t be used alone. It must always follow a format type.
Format types and corresponding styles
The different types support different styles:
Type: none
Type: number
Type: date
In addition to these predefined styles, we can also provide our own subformat pattern:
Example:
Conclusion
Now we know about the different ways to format Strings. Which one to choose depends on our requirements.
java.text.MessageFormat
is easier on the eyes, especially if you’re not fluent in printf
.
But String.format
is widely used and understood, so we can’t go wrong with it.
And the printf
format specifiers aren’t only used by Java, so we learn a more universal skill.
Resources
Java Documentation (Oracle)
Other
printf
Format String (Wikipedia)- Guide to
java.util.Formatter
(Baeldung) - Formatting with
printf
(Baeldung)