# How to format a string in Java

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Oct 3, 2021, updated Oct 29, 2022. Topics: Java.
Canonical URL: https://attacomsian.com/blog/java-string-format

> A quick guide to learn how to use the String.format() method and the MessageFormat class to format strings in Java.

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

## Formatting a string using the `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:

```java
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:

```java
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](https://attacomsian.com/blog/data-type-conversions-java) into a string:

```java
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:

```java
// 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
```

Read [this article](https://attacomsian.com/blog/java-convert-integer-to-string) to learn more about 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.

```java
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 the 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:

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

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

You can also print multiple specifiers to the same argument:

```java
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, they are ignored.

### 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:

```java
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 the date and time conversion above. The full list can be found [here](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Formatter.html)|
|`%x`|Integer (incl. byte, short, int, long, BigInt)|Hex string|


## Formatting a string using the `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:

```java
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.

## Formatting a string using the `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`:

```java
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
```

## Formatting a string using the `Formatter` class

The above three methods use the `Formatter` class under to hood 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:

```java
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` making it a more flexible option:

```java
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
```

## Formatting a string using the `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:

```java
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 look at the third pattern &mdash; `{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:

```java
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](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/MessageFormat.html).
