When building reports, logs, or user-facing messages, you need precise control over how data appears. String formatting creates aligned columns, fixed decimal places, reusable templates, and consistent spacing.

Basic Format Specifiers

Basics.java
// Basic format specifiers

public class Basics {

    public static void main(String[] args) {
        // String
        String name = ;
        String greeting = String.format("Hello, %s!", name);
        System.out.println(greeting);

        // Integer
        int age = 25;
        String ageStr = String.format("Age: %d", age);
        System.out.println(ageStr);

        // Float
        double price = ;
        String priceStr = String.format("Price: $%f", price);
        System.out.println(priceStr);

        // Multiple arguments
        String msg = String.format("%s is %d years old and has $%.2f", 
                                    name, age, price);
        System.out.println(msg);

        // Direct printing with printf
        System.out.printf("Name: %s, Age: %d%n", "Bob", 30);

        // Different types
        String formatted = String.format(
            "String: %s, Int: %d, Float: %.2f, Boolean: %b",
            "test", 42, 3.14159, true
        );
        System.out.println(formatted);
    }

}
// Basic format specifiers

public class Basics {

    public static void main(String[] args) {
        // String
        String name = ;
        String greeting = String.format("Hello, %s!", name);
        System.out.println(greeting);

        // Integer
        int age = 25;
        String ageStr = String.format("Age: %d", age);
        System.out.println(ageStr);

        // Float
        double price = ;
        String priceStr = String.format("Price: $%f", price);
        System.out.println(priceStr);

        // Multiple arguments
        String msg = String.format("%s is %d years old and has $%.2f", 
                                    name, age, price);
        System.out.println(msg);

        // Direct printing with printf
        System.out.printf("Name: %s, Age: %d%n", "Bob", 30);

        // Different types
        String formatted = String.format(
            "String: %s, Int: %d, Float: %.2f, Boolean: %b",
            "test", 42, 3.14159, true
        );
        System.out.println(formatted);
    }

}
// Basic format specifiers

public class Basics {

    public static void main(String[] args) {
        // String
        String name = ;
        String greeting = String.format("Hello, %s!", name);
        System.out.println(greeting);

        // Integer
        int age = 25;
        String ageStr = String.format("Age: %d", age);
        System.out.println(ageStr);

        // Float
        double price = ;
        String priceStr = String.format("Price: $%f", price);
        System.out.println(priceStr);

        // Multiple arguments
        String msg = String.format("%s is %d years old and has $%.2f", 
                                    name, age, price);
        System.out.println(msg);

        // Direct printing with printf
        System.out.printf("Name: %s, Age: %d%n", "Bob", 30);

        // Different types
        String formatted = String.format(
            "String: %s, Int: %d, Float: %.2f, Boolean: %b",
            "test", 42, 3.14159, true
        );
        System.out.println(formatted);
    }

}
// Basic format specifiers

public class Basics {

    public static void main(String[] args) {
        // String
        String name = ;
        String greeting = String.format("Hello, %s!", name);
        System.out.println(greeting);

        // Integer
        int age = 25;
        String ageStr = String.format("Age: %d", age);
        System.out.println(ageStr);

        // Float
        double price = ;
        String priceStr = String.format("Price: $%f", price);
        System.out.println(priceStr);

        // Multiple arguments
        String msg = String.format("%s is %d years old and has $%.2f", 
                                    name, age, price);
        System.out.println(msg);

        // Direct printing with printf
        System.out.printf("Name: %s, Age: %d%n", "Bob", 30);

        // Different types
        String formatted = String.format(
            "String: %s, Int: %d, Float: %.2f, Boolean: %b",
            "test", 42, 3.14159, true
        );
        System.out.println(formatted);
    }

}
format_specifier A placeholder like %s, %d, or %.2f that gets replaced with an argument value during formatting.

Width and Precision

Width controls minimum output size. Precision controls digits after the decimal point for floating-point output.

WidthPrecision.java
// Width and precision

public class WidthPrecision {

    public static void main(String[] args) {
        // Minimum width
        System.out.println(String.format("|%10s|", "Hello"));
        System.out.println(String.format("|%10s|", "Hi"));

        // Left align with -
        System.out.println(String.format("|%-10s|", "Hello"));
        System.out.println(String.format("|%-10s|", "Hi"));

        // Right align integers
        System.out.println(String.format("|%5d|", 42));
        System.out.println(String.format("|%5d|", 12345));

        // Zero padding
        System.out.println(String.format("%05d", 42));
        System.out.println(String.format("%08d", 123));

        // Precision for floats
        double pi = ;
        System.out.println("\nPrecision examples:");
        System.out.println(String.format("%.2f", pi));  // 2 decimals
        System.out.println(String.format("%.4f", pi));  // 4 decimals
        System.out.println(String.format("%.0f", pi));  // 0 decimals

        // Width and precision combined
        System.out.println("\nWidth + Precision:");
        System.out.println(String.format("|%10.2f|", pi));
        System.out.println(String.format("|%10.4f|", 1.5));

        // Table formatting
        System.out.println("\nTable:");
        System.out.printf("%-10s %5s %8s%n", "Name", "Age", "Score");
        System.out.printf("%-10s %5d %8.2f%n", "Alice", 25, 95.5);
        System.out.printf("%-10s %5d %8.2f%n", "Bob", 30, 87.25);
        System.out.printf("%-10s %5d %8.2f%n", "Charlie", 22, 92.0);
    }

}
// Width and precision

public class WidthPrecision {

    public static void main(String[] args) {
        // Minimum width
        System.out.println(String.format("|%10s|", "Hello"));
        System.out.println(String.format("|%10s|", "Hi"));

        // Left align with -
        System.out.println(String.format("|%-10s|", "Hello"));
        System.out.println(String.format("|%-10s|", "Hi"));

        // Right align integers
        System.out.println(String.format("|%5d|", 42));
        System.out.println(String.format("|%5d|", 12345));

        // Zero padding
        System.out.println(String.format("%05d", 42));
        System.out.println(String.format("%08d", 123));

        // Precision for floats
        double pi = ;
        System.out.println("\nPrecision examples:");
        System.out.println(String.format("%.2f", pi));  // 2 decimals
        System.out.println(String.format("%.4f", pi));  // 4 decimals
        System.out.println(String.format("%.0f", pi));  // 0 decimals

        // Width and precision combined
        System.out.println("\nWidth + Precision:");
        System.out.println(String.format("|%10.2f|", pi));
        System.out.println(String.format("|%10.4f|", 1.5));

        // Table formatting
        System.out.println("\nTable:");
        System.out.printf("%-10s %5s %8s%n", "Name", "Age", "Score");
        System.out.printf("%-10s %5d %8.2f%n", "Alice", 25, 95.5);
        System.out.printf("%-10s %5d %8.2f%n", "Bob", 30, 87.25);
        System.out.printf("%-10s %5d %8.2f%n", "Charlie", 22, 92.0);
    }

}
width The minimum number of characters used for a formatted value, padding with spaces if needed.
precision For floating-point numbers, the number of digits shown after the decimal point.

printf Output

printf writes formatted output directly instead of first creating a String.

Printf.java
// Printf style formatting

public class Printf {

    public static void main(String[] args) {
        // printf prints directly (no assignment)
        System.out.printf("Hello, %s!%n", "World");

        // Format and print in one call
        String name = "Alice";
        int age = 25;
        double salary = 75000.50;

        System.out.printf("Employee: %s%n", name);
        System.out.printf("Age: %d years%n", age);
        System.out.printf("Salary: $%.2f%n", salary);

        // Multiple values in one printf
        System.out.printf("%n%s is %d years old and earns $%.2f%n", 
                         name, age, salary);

        // Formatting numbers
        System.out.println("\nNumber formats:");
        System.out.printf("Decimal: %d%n", 42);
        System.out.printf("Hex: %x%n", 255);
        System.out.printf("Octal: %o%n", 8);
        System.out.printf("Scientific: %e%n", 12345.6789);

        // Signs
        System.out.println("\nSigns:");
        System.out.printf("Positive with +: %+d%n", 42);
        System.out.printf("Negative: %+d%n", -42);
        System.out.printf("Space for positive: % d%n", 42);

        // Grouping separator
        System.out.println("\nGrouping:");
        System.out.printf("Large number: %,d%n", 1234567890);
        System.out.printf("Float grouped: %,.2f%n", 1234567.89);

        // Report example
        System.out.println("\n=== Sales Report ===");
        System.out.printf("%-15s: %,10d%n", "Units Sold", 1250);
        System.out.printf("%-15s: $%,10.2f%n", "Revenue", 125000.75);
        System.out.printf("%-15s: $%,10.2f%n", "Profit", 45000.25);
    }

}

Argument Index

ArgumentIndex.java
// Argument index

public class ArgumentIndex {

    public static void main(String[] args) {
        // Reuse arguments with index
        String msg1 = String.format("%1$s has %2$d apples. %1$s likes apples.",
                                     "Alice", 5);
        System.out.println(msg1);

        // Reverse order
        String msg2 = String.format("%2$s %1$s", "World", "Hello");
        System.out.println(msg2);

        // Date formatting with index
        int year = 2025, month = 1, day = 29;
        String date1 = String.format("%1$d-%2$02d-%3$02d", year, month, day);
        String date2 = String.format("%2$02d/%3$02d/%1$d", year, month, day);

        System.out.println("\nDate formats:");
        System.out.println("ISO: " + date1);
        System.out.println("US:  " + date2);

        // Same value, different formats
        double value = 1234.567;
        String formatted = String.format(
            "As is: %1$f, Rounded: %1$.2f, Scientific: %1$e",
            value
        );
        System.out.println("\n" + formatted);

        // Locale-specific formatting
        String msg3 = String.format(
            "%1$s costs $%2$.2f. Buy %3$d %1$s for $%4$.2f",
            "Apple", 1.50, 10, 15.00
        );
        System.out.println("\n" + msg3);
    }

}
argument_index The %n$ syntax references arguments by position, allowing the same value to be reused or reordered.

Text Blocks

Java text blocks make multi-line templates easier to read before formatting them.

TextBlocks.java
// Text blocks (Java 15+)

public class TextBlocks {

    public static void main(String[] args) {
        // Text block (preserves formatting)
        String json = """
                {
                    "name": "Alice",
                    "age": 25,
                    "city": "New York"
                }
                """;
        System.out.println(json);

        // Text block with formatting
        String name = "Bob";
        int age = 30;

        String jsonFormatted = """
                {
                    "name": "%s",
                    "age": %d,
                    "active": true
                }
                """.formatted(name, age);
        System.out.println(jsonFormatted);

        // HTML template
        String title = "Welcome";
        String content = "This is a text block example.";

        String html = """
                <html>
                    <head>
                        <title>%s</title>
                    </head>
                    <body>
                        <h1>%s</h1>
                        <p>%s</p>
                    </body>
                </html>
                """.formatted(title, title, content);
        System.out.println(html);

        // SQL query
        String table = "users";
        String condition = "age > 21";

        String sql = """
                SELECT *
                FROM %s
                WHERE %s
                ORDER BY name;
                """.formatted(table, condition);
        System.out.println(sql);

        // Table with alignment
        String[][] data = {
            {"Alice", "25", "Engineer"},
            {"Bob", "30", "Designer"},
            {"Charlie", "35", "Manager"}
        };

        System.out.println("\nEmployee Table:");
        System.out.printf("%-10s %-5s %-12s%n", "Name", "Age", "Title");
        System.out.println("-".repeat(30));
        for (String[] row : data) {
            System.out.printf("%-10s %-5s %-12s%n", row[0], row[1], row[2]);
        }
    }

}

Practical Formatting

Formatting is commonly used for reports, logs, progress displays, and aligned statistics.

Practical.java
// Practical formatting examples

public class Practical {

    public static void printInvoice(String customer, String[][] items) {
        System.out.println("=".repeat(50));
        System.out.printf("INVOICE FOR: %s%n", customer);
        System.out.println("=".repeat(50));
        System.out.printf("%-20s %8s %10s %12s%n", 
                         "Item", "Qty", "Price", "Total");
        System.out.println("-".repeat(50));

        double grandTotal = 0;
        for (String[] item : items) {
            String name = item[0];
            int qty = Integer.parseInt(item[1]);
            double price = Double.parseDouble(item[2]);
            double total = qty * price;
            grandTotal += total;

            System.out.printf("%-20s %8d $%9.2f $%11.2f%n",
                             name, qty, price, total);
        }

        System.out.println("-".repeat(50));
        System.out.printf("%41s $%11.2f%n", "GRAND TOTAL:", grandTotal);
        System.out.println("=".repeat(50));
    }

    public static void printProgress(String task, int percent) {
        int barWidth = 30;
        int filled = (int) (barWidth * percent / 100.0);
        String bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
        System.out.printf("\r%-20s [%s] %3d%%", task, bar, percent);
    }

    public static void log(String level, String message) {
        long timestamp = 1706500800000L;
        String formatted = String.format("[%d] %-7s: %s",
                                        timestamp, level, message);
        System.out.println(formatted);
    }

    public static void printStatistics(String[] labels, double[] values) {
        System.out.println("\nStatistics:");
        System.out.println("-".repeat(30));

        for (int i = 0; i < labels.length; i++) {
            System.out.printf("%-15s: %12.2f%n", labels[i], values[i]);
        }
    }

    public static void main(String[] args) {
        // Invoice
        String[][] items = {
            {"Widget A", "5", "19.99"},
            {"Widget B", "3", "29.99"},
            {"Widget C", "10", "9.99"}
        };
        String customer = ;
        printInvoice(customer, items);

        // Progress bars
        System.out.println("\n\nProgress Demo:");
        printProgress("Downloading", 0);
        printProgress("Downloading", 50);
        printProgress("Downloading", 100);
        System.out.println();

        // Logs
        System.out.println("\nLog Entries:");
        log("INFO", "Application started");
        log("WARNING", "Low memory");
        log("ERROR", "Connection failed");

        // Statistics
        String[] statLabels = {"Mean", "Median", "Std Dev", "Min", "Max"};
        double[] statValues = {75.5, 72.0, 12.3, 45.0, 98.0};
        printStatistics(statLabels, statValues);
    }

}
// Practical formatting examples

public class Practical {

    public static void printInvoice(String customer, String[][] items) {
        System.out.println("=".repeat(50));
        System.out.printf("INVOICE FOR: %s%n", customer);
        System.out.println("=".repeat(50));
        System.out.printf("%-20s %8s %10s %12s%n", 
                         "Item", "Qty", "Price", "Total");
        System.out.println("-".repeat(50));

        double grandTotal = 0;
        for (String[] item : items) {
            String name = item[0];
            int qty = Integer.parseInt(item[1]);
            double price = Double.parseDouble(item[2]);
            double total = qty * price;
            grandTotal += total;

            System.out.printf("%-20s %8d $%9.2f $%11.2f%n",
                             name, qty, price, total);
        }

        System.out.println("-".repeat(50));
        System.out.printf("%41s $%11.2f%n", "GRAND TOTAL:", grandTotal);
        System.out.println("=".repeat(50));
    }

    public static void printProgress(String task, int percent) {
        int barWidth = 30;
        int filled = (int) (barWidth * percent / 100.0);
        String bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
        System.out.printf("\r%-20s [%s] %3d%%", task, bar, percent);
    }

    public static void log(String level, String message) {
        long timestamp = 1706500800000L;
        String formatted = String.format("[%d] %-7s: %s",
                                        timestamp, level, message);
        System.out.println(formatted);
    }

    public static void printStatistics(String[] labels, double[] values) {
        System.out.println("\nStatistics:");
        System.out.println("-".repeat(30));

        for (int i = 0; i < labels.length; i++) {
            System.out.printf("%-15s: %12.2f%n", labels[i], values[i]);
        }
    }

    public static void main(String[] args) {
        // Invoice
        String[][] items = {
            {"Widget A", "5", "19.99"},
            {"Widget B", "3", "29.99"},
            {"Widget C", "10", "9.99"}
        };
        String customer = ;
        printInvoice(customer, items);

        // Progress bars
        System.out.println("\n\nProgress Demo:");
        printProgress("Downloading", 0);
        printProgress("Downloading", 50);
        printProgress("Downloading", 100);
        System.out.println();

        // Logs
        System.out.println("\nLog Entries:");
        log("INFO", "Application started");
        log("WARNING", "Low memory");
        log("ERROR", "Connection failed");

        // Statistics
        String[] statLabels = {"Mean", "Median", "Std Dev", "Min", "Max"};
        double[] statValues = {75.5, 72.0, 12.3, 45.0, 98.0};
        printStatistics(statLabels, statValues);
    }

}

Exercise: Practical.java

Format a product receipt with aligned columns showing item name, quantity, unit price, and total