There are many ways to format a string in Java. You can either use the String.format() method, the printf() method, or the MessageFormat class for formatting strings.

String.format() method

The most common way of formatting a string in Java is using the String.format() method. This static method returns a formatted string using the given locale, format string, and arguments.

Here is an example:

String name = "John Doe";
String str = String.format("My name is %s", name);
System.out.println(str);
// My name is John Doe

Width and Padding

The String.format() method also allows us to set the width, alignment, and padding of the formatted string:

String message = "Hey 👋";

// Text width
String.format("|%20s|", message);
// |              Hey 👋|

// Left justify text
String.format("|%-20s|", message);
// |Hey 👋              |

// Maximum number of characters
String.format("|%.3s|", message);
// |Hey|

// Max. characters with width
String.format("|%20.3s|", message);
// |                 Hey|

Conversions

Besides formatting, the String.format() method can also be used to convert and format other data types into a string:

String str1 = String.format("%d", 999);     // Integer value
String str2 = String.format("%f", 56.7);    // Float value
String str3 = String.format("%x", 678);     // Hexadecimal value
String str4 = String.format("%o", 99);     // Octal value
String str5 = String.format("%tc", new Date());     // Date object
String str6 = String.format("%c", 'A');     // Char value

System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
System.out.println(str4);
System.out.println(str5);
System.out.println(str6);

// 999
// 56.700000
// 2a6
// 143
// Sun Oct 03 14:05:44 PKT 2021
// A

Just like strings, you can also specify width and padding for other data types:

// Text width
String.format("|%10d|", 999);    // |       999|

// Justify left
String.format("|%-10d|", 999);  // |999       |

// Pad with zeros
String.format("|%010d|", 999);  // |0000000999|

// Positive number
String.format("%+d", 999);      // +999

// Thousands separator
String.format("%,d", 9999999);  // 9,999,999

// Enclose -ve number with parenthesis
String.format("%o", 99);    // (99)

// Alternative Hex & Octal formatting
String.format("%#x", 99);    // 0x63
String.format("%#o", 99);    // 0143

Take a look at this article to learn more about an integer to string conversion in Java.

Argument Index

The argument index is an integer indicating the position of the argument in the argument list. The first argument is referenced by 1$, the second by 2$, and so on.

String product = "Pizza 🍕";
double price = 5.99;

String str = String.format("The price of %2$s is USD %1$.2f", price, product);

System.out.println(str);
// The price of Pizza 🍕 is USD 5.99

With argument index, the order of the arguments does not matter. So you can pass the arguments in any order.

Another way to reference arguments by position is to use the < flag that causes the argument for the previous format specifier to be re-used:

String str = String.format("Today is %1$tB %<td, %<tY", LocalDate.now());

System.out.println(str);
// Today is October 03, 2021

You can also point multiple specifiers to the same argument:

String str = String.format("%2$d + %2$d = 4", 1, 2);

System.out.println(str);
// 2 + 2 = 4

If there are more arguments than format specifiers, the extra arguments are ignored as shown above.

Localization

By default, the String.format() method uses the default locale by calling the Locale.getDefault() method.

To localize the formatted string, you have to pass a valid locale as the first argument as shown below:

int number = 4566778;
String withoutLocale = String.format("%,d", number);
String withLocale = String.format(Locale.GERMAN, "%,d", number);

System.out.println(withoutLocale); // 4,566,778
System.out.println(withLocale);    // 4.566.778

Notice the additional , flag before d in the format string. This flag is used to include locale-specific grouping separators.

Format Specifiers

Finally, here is a list of all format specifiers supported by the String.format() method:

Specifier Data Type Output
%a Floating point (except BigDecimal) Hex output of floating-point number
%b Any type “true” if non-null, “false” if null
%c Character Unicode character
%d Integer (incl. byte, short, int, long, BigInt) Decimal Integer
%e Floating point Decimal number in scientific notation
%f Floating point Decimal number
%g Floating point Decimal number, possibly in scientific notation depending on the precision and value.
%h Any type Hex String of value from hashCode() method.
%n None Platform-specific line separator.
%o Integer (incl. byte, short, int, long, BigInt) Octal number
%s Any type String value
%t Date/Time (includes long, Calendar, Date, and TemporalAccessor) %t is the prefix for date and time conversions. More formatting flags are needed after this. See date and time conversion above. The full list can be found here
%x Integer (incl. byte, short, int, long, BigInt) Hex string

System.out.printf() method

Another way of formatting strings in Java is using the printf() method. This method prints the contents on the standard output stream and does not return anything:

System.out.printf("I am %s!%n", "John Doe");
System.out.printf("Total price is %.2f USD%n", 99.3);
System.out.printf("Today date is %tD%n", LocalDate.now());

// I am John Doe!
// Total price is 99.30 USD
// Today date is 10/03/21

The printf() method uses the same underlying principles as the String.format() method. This is because both these methods internally use the Formatter class to format strings. Thus, everything said for String.format() also applies to the printf() method.

The only difference is the return type; printf() prints the formatted string to the standard output stream (mostly console), whereas String.format() returns the formatted string. This makes String.format() more versatile as you can use the returned value in more than one way.

String.formatted() method

The String.formatted() method was introduced in Java 15 for formatting an instance of the String class using the supplied arguments.

This method is equivalent to String.format() with default locale except that it must be called on an already declared instance of String:

String str = "Date is %tD and time is %tT";
String formatted = str.formatted(LocalDate.now(), LocalTime.now());

System.out.println(formatted);
// Date is 10/03/21 and time is 16:13:57

Formatter class

All of the above three methods internally use the Formatter class to format strings. You can use the same specifiers to format a string using any of them. They only differ on return type and whether to create an instance or not.

To use the Formatter class directly, you need to instantiate a new instance by using its constructor:

Formatter formatter = new Formatter();
formatter.format("Date is %tD and time is %tT", LocalDate.now(), LocalTime.now());

System.out.println(formatter);
// Date is 10/03/21 and time is 16:25:07

The Formatter class also works with StringBuilder that makes it a more flexible option:

StringBuilder builder = new StringBuilder();
Formatter formatter = new Formatter(builder);
formatter.format("Date is %tD and time is %tT", LocalDate.now(), LocalTime.now());
System.out.println(builder);
// Date is 10/03/21 and time is 16:30:32

MessageFormat class

Finally, the last way of formatting strings in Java that does not use Formatter under the hood is the MessageFormat class.

The MessageFormat class provides methods to create concatenated messages in a language-neutral way. It means the formatted messages will be the same regardless of the programming language used to construct them. This makes it suitable to create messages that are displayed to the end-users.

The MessageFormat class takes in a set of objects, formats them, and then replaces the patterns at the appropriate places with the formatted strings.

Here is an example:

String name = "John Doe";
String buy = "a coffee for $3.49";

String str = MessageFormat.format("{0} bought {1} on {2, date, long} at {2, time}.",
        name, buy, new Date());

System.out.println(str);
// John Doe bought a coffee for $3.49 on 3 October 2021 at 9:30:47 pm.

As you can see above, we are using curly brackets ({}) called a pattern for each of the arguments instead of percentage specifiers (%).

Let us take a look at the third pattern — {2, date, long}. The number 2 refers to the index of the argument that should be inserted in its place. In our case, it is a Date object.

The second part, date, represents the format type of the argument. There are four top-level format types: number, date, time, and choice.

The last part, long, represents the format style used to make a more specified selection. The date format type has short, medium, long, and full as format styles.

The MessageFormat class also supports localization of the messages:

MessageFormat form = new MessageFormat("{0} price starts from {1, number, currency}", 
        Locale.US);

System.out.println(form.format(new Object[]{"Tesla", 39900}));
// Tesla price starts from $39,900.00

For a complete list of format types and format styles, visit the documentation.

✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.