The printf Method
How do we print text and numbers exactly the way we want?
Prepared by: Eng. Badereddin Mohammed Elhalimi · Eng. Mohammed Zuhair Kouhail
By the end of this lecture you will be able to
- Explain the parts of a
printfline: the command, the template and the values - Choose the right format specifier for each value
- Tell a compile error from a run-time error
- Control decimal places, width and alignment
- Print a neat table, and build formatted text with
String.format
In this lecture
printfworks like a form with blanks- Every
printfline has three parts - Five format specifiers cover the basics
%tneeds a suffix and a date value- Each blank takes its value in order
- A wrong specifier passes the compiler and fails while running
- A compile error prevents running; a run-time error appears during it
- Missing values and mismatched specifiers also fail at run time
%.2fsets the number of decimal places- Width reserves columns:
%5daligns right and%-10saligns left %05d,%c,%band%%complete the toolbox- Fixed widths print a table with straight columns
String.formatbuilds the formatted text without printing it- Recap:
printf= template + specifiers + values - Review questions
printf works like a form with blanks
The sentence with blanks. The sentence stays fixed, and each %s is an empty box waiting for a value.
"Hello %s!"What fills the blank.
"World"What you see on screen.
Hello World!Fill the blank
Predict the output, then run. Change World to your name and run again.
public class Form {
public static void main(String[] args) {
System.out.printf("Hello %s!%n", "World");
}
}Hello World!
Every printf line has three parts
| Part | In the example | Meaning |
|---|---|---|
| 1. The command | System.out.printf | Print using the format I give you. |
| 2. The template | "Hello %s!%n" | Fixed text with blanks to fill: %s and %n. |
| 3. The values | "World" | What goes into the blanks, separated by commas. |
We forgot %n on the first line. What does the program print?
public class NoNewLine {
public static void main(String[] args) {
System.out.printf("Hello %s!", "Sara");
System.out.printf("Hello %s!%n", "Ali");
}
}Show the output
Hello Sara!Hello Ali!
Why? printf prints only the template, so without %n the cursor stays on the same line. Press "Debug line by line" and watch where the output goes after each statement.
Five format specifiers cover the basics
| Specifier | Value | Example | Output | Memory trick |
|---|---|---|---|---|
%s | Text (String) | ("%s", "Ali") | Ali | s = string: text as it is |
%d | Whole number | ("%d", 25) | 25 | d = decimal: no decimal point |
%f | Decimal number | ("%f", 3.14) | 3.140000 | f = float: 6 decimals |
%t | Date and time | ("%tY", d) | 2026 | t = time, and Y means year |
%n | New line | ("A%nB") | A, B | n = new line: like pressing Enter |
Try the specifiers
Predict each line. Then change the values, and add %n inside one of the texts to split it into two lines.
public class Specifiers {
public static void main(String[] args) {
System.out.printf("%s%n", "Ali");
System.out.printf("%d%n", 25);
System.out.printf("%f%n", 3.14);
System.out.printf("A%nB%n");
}
}Ali 25 3.140000 A B
What does the d in %d mean?
%f, and dates to %t.%t needs a suffix and a date value
%t alone is not enough: the letter after it picks the part of the date, and Y means the year. The value itself must be a date, not an ordinary number.
Print the year
We use a fixed date so the output stays fixed. In GregorianCalendar, months count from 0, so 0 means January. Change the year to 2030 and run.
public class YearOnly {
public static void main(String[] args) {
System.out.printf("%tY%n", new java.util.GregorianCalendar(2026, 0, 1));
}
}2026
Each blank takes its value in order
Two blanks, two values
Order matters: the 1st blank takes the 1st value, the 2nd takes the 2nd. Type matters: a number blank needs a number, and a text blank needs text.
public class NameAge {
public static void main(String[] args) {
System.out.printf("Name: %s, Age: %d%n", "Ali", 19);
}
}Name: Ali, Age: 19
Quick check: what will be printed?
public class Blanks {
public static void main(String[] args) {
System.out.printf("%d + %d = %d", 2, 3, 5);
}
}Show the output
2 + 3 = 5
Why? Each %d takes the next value in order: the 1st gets 2, the 2nd gets 3, the 3rd gets 5.
Quick check: which specifier fits the blank to print the price?
System.out.printf("Price: ___", 4.5);
%f. The output is Price: 4.500000.A wrong specifier passes the compiler and fails while running
Quick check: spot the mistake. What happens when this line runs?
System.out.printf("Age: %d", "19");
"19" in quotes is text (a String), and %d needs a whole number. The compiler does not read inside the template, so only the JVM notices, on reaching the blank.Watch it fail
Run the program: Age: appears first, then the message java.util.IllegalFormatConversionException: d != java.lang.String. Then press "Debug line by line": compiling succeeds with no problem, and the failure happens at this line while it runs.
public class AgeError {
public static void main(String[] args) {
System.out.printf("Age: %d", "19");
System.out.println("This line never runs");
}
}Age:
| In the message | What it means |
|---|---|
IllegalFormatConversionException | An exception: the value does not fit the specifier. |
d | The specifier: %d. |
!= | Does not fit. |
java.lang.String | The type of the value we gave: text. |
A compile error prevents running; a run-time error appears during it
| Compare | Compile error | Run-time error |
|---|---|---|
| Who finds it? | The compiler, javac | The JVM, while running |
| Does the program run? | No, no .class file is produced | Yes, until it reaches the bad line |
| Any output? | Nothing | Whatever printed before the error |
| Example | int age = "19"; | printf("Age: %d", "19"); |
The same mistake, two different fates. In int age = "19"; the compiler knows the variable's type, so it rejects the line. But to the compiler, a printf template is just text, and any value after it is accepted.
This one is a compile error: the program never runs
Notice that Age: never appears here. Remove the quotation marks.
public class AgeCompile {
public static void main(String[] args) {
int age = "19";
System.out.printf("Age: %d%n", age);
}
}incompatible types: String cannot be converted to intShow the fix
public class AgeCompile {
public static void main(String[] args) {
int age = 19;
System.out.printf("Age: %d%n", age);
}
}Age: 19
Why? The compiler knows age is an int, so it stops before anything runs. That is why nothing prints.
This is a compile error too: the missing comma
The compiler does not read inside the template, but it does check the shape of the line. Add the comma between the template and the value.
public class AgeComma {
public static void main(String[] args) {
System.out.printf("Age: %d%n" 19);
}
}')' expectedShow the fix
public class AgeComma {
public static void main(String[] args) {
System.out.printf("Age: %d%n", 19);
}
}Age: 19
Why? The message looks unrelated to the cause: the compiler asks for ) because after the template it expects a comma or a closing parenthesis, and it found 19. The real cause is the missing comma.
Fix the run-time error
This program compiles but fails when it runs. Fix it to print Age: 19. There are two ways: remove the quotes around the value, or use %s.
public class AgeFix {
public static void main(String[] args) {
System.out.printf("Age: %d%n", "19");
}
}Age: 19
Hint 1
"19" is text, and 19 is a number.
Solution
public class AgeFix {
public static void main(String[] args) {
System.out.printf("Age: %d%n", 19);
}
}Missing values and mismatched specifiers also fail at run time
| The line | The message after Exception in thread "main" | Why |
|---|---|---|
printf("%d", 4.5); | IllegalFormatConversionException: d != java.lang.Double | %d does not accept a decimal |
printf("%f", 5); | IllegalFormatConversionException: f != java.lang.Integer | %f does not accept 5; write 5.0 |
printf("%s %d%n", "Ali"); | MissingFormatArgumentException: Format specifier '%d' | Two blanks and one value |
printf("%t", date); | UnknownFormatConversionException: Conversion = 't' | %t needs a suffix, like %tY |
We swapped the two values. What appears in the output before the error?
public class Swapped {
public static void main(String[] args) {
System.out.printf("Name: %s, Age: %d%n", 19, "Ali");
}
}Show the output
Name: 19, Age:
Why? %s accepts any value, so it prints 19. Then %d reaches the text "Ali" and the program stops. That is why the start of the output can look fine while the mistake is elsewhere.
A missing value
Run the program and read the message, then add the value 19 after "Ali".
public class Missing {
public static void main(String[] args) {
System.out.printf("%s %d%n", "Ali");
}
}Ali
%.2f sets the number of decimal places
%f always prints 6 decimal places, which we rarely want. The number after the dot sets the places, and the value is rounded for printing only; the variable itself does not change.
Change the number of places
Change %.2f to %.3f, then to %.0f, and predict the output each time.
public class Precision {
public static void main(String[] args) {
double pi = 3.14159;
System.out.printf("%f%n", pi);
System.out.printf("%.2f%n", pi);
System.out.println(pi);
}
}3.141590 3.14 3.14159
Does %.1f cut the digits or round them?
public class Rounding {
public static void main(String[] args) {
System.out.printf("%.1f%n", 2.75);
}
}Show the output
2.8
Why? %.1f rounds to one place rather than cutting, so 2.75 becomes 2.8.
The receipt total
The price is 12.5 and the quantity is 3. Calculate the total in a double variable and print it with two decimal places, as in the expected output.
public class Receipt {
public static void main(String[] args) {
double price = 12.5;
int quantity = 3;
// Calculate the total and print it with printf
}
}Total: 37.50
Hint 1
The template is "Total: %.2f%n".
Solution
public class Receipt {
public static void main(String[] args) {
double price = 12.5;
int quantity = 3;
double total = price * quantity;
System.out.printf("Total: %.2f%n", total);
}
}Width reserves columns: %5d aligns right and %-10s aligns left
| Format | Meaning | Value | Output between | |
|---|---|---|---|
%5d | 5 columns, aligned right | 42 | | 42| |
%-5d | 5 columns, aligned left | 42 | |42 | |
%-10s | 10 columns, aligned left | "Ali" | |Ali | |
%8.2f | 8 columns, 2 of them decimals | 3.14159 | | 3.14| |
The bars reveal the spaces
We put | around each value so you can see the spaces. Delete the - from %-10s: where did the name go?
public class Width {
public static void main(String[] args) {
System.out.printf("|%5d|%n", 42);
System.out.printf("|%-10s|%n", "Ali");
System.out.printf("|%8.2f|%n", 3.14159);
}
}| 42| |Ali | | 3.14|
The name is longer than the width. What happens?
public class TooLong {
public static void main(String[] args) {
System.out.printf("|%3s|%n", "Mohammed");
}
}Show the output
|Mohammed|
Why? Width is a minimum, not a maximum: Java never cuts the value, it takes the columns it needs.
%05d, %c, %b and %% complete the toolbox
| Format | Value | Output | Use |
|---|---|---|---|
%05d | 42 | 00042 | Fills empty columns with zeros, like a student number |
%c | 'A' | A | One char |
%b | true | true | A boolean value |
%% | Needs no value | % | The percent sign itself |
All four together
Change %05d to %07d, change passed to false, then run. Why does %% have no matching value?
public class Toolbox {
public static void main(String[] args) {
int id = 42;
char grade = 'A';
boolean passed = true;
System.out.printf("ID: %05d%n", id);
System.out.printf("Grade: %c%n", grade);
System.out.printf("Passed: %b%n", passed);
System.out.printf("Score: %d%%%n", 95);
}
}ID: 00042 Grade: A Passed: true Score: 95%
How many % signs appear in the output?
public class Percent {
public static void main(String[] args) {
System.out.printf("Discount: 50%%%n");
}
}Show the output
Discount: 50%
Why? %% prints one sign, and %n is a new line. A lone % at the end of the template fails at run time with UnknownFormatConversionException.
Fixed widths print a table with straight columns
The student table
The first line is the header, using the same widths as the rows below it. Press "Debug line by line" and watch the table build line by line. Then add a fourth student.
public class StudentTable {
public static void main(String[] args) {
System.out.printf("%-10s%5s%8s%n", "Name", "Age", "GPA");
System.out.printf("%-10s%5d%8.2f%n", "Sara", 19, 3.75);
System.out.printf("%-10s%5d%8.2f%n", "Ahmed", 20, 3.2);
System.out.printf("%-10s%5d%8.2f%n", "Mohammed", 21, 2.5);
}
}Name Age GPA Sara 19 3.75 Ahmed 20 3.20 Mohammed 21 2.50
The price table
Print the expected table: the item name in width 8 aligned left, and the price in width 6 with two decimals. Book costs 12.5 and Pen costs 1.75.
public class PriceTable {
public static void main(String[] args) {
// Print the header, then one line for each item
}
}Item Price Book 12.50 Pen 1.75
Hint 1
The header template is "%-8s%6s%n".
Hint 2
The row template is "%-8s%6.2f%n".
Solution
public class PriceTable {
public static void main(String[] args) {
System.out.printf("%-8s%6s%n", "Item", "Price");
System.out.printf("%-8s%6.2f%n", "Book", 12.5);
System.out.printf("%-8s%6.2f%n", "Pen", 1.75);
}
}String.format builds the formatted text without printing it
String.format uses the same template and values, but returns the text instead of printing it. We save it in a String variable and use it later.
Save the text, then print it
Press "Debug line by line". Nothing prints after the first line; instead, a line box appears holding the finished text, which we print twice without formatting it again.
public class FormatText {
public static void main(String[] args) {
String line = String.format("%s: %.2f", "GPA", 3.756);
System.out.println(line);
System.out.println(line);
}
}GPA: 3.76 GPA: 3.76
Notice that the result of String.format is neither saved nor printed. What does the program print?
public class FormatOnly {
public static void main(String[] args) {
String.format("%05d", 42);
System.out.println("Done");
}
}Show the output
Done
Why? String.format only returns the text. If we do not use what it returns, it is lost. Printing is the job of printf and println.
The student code
Use String.format to build the code from the number 7, in 4 columns with leading zeros, and save it in the variable code. Then print Code: followed by its value using println.
public class StudentCode {
public static void main(String[] args) {
// Build the code with String.format, then print it
}
}Code: 0007
Hint 1
%04d means 4 columns with leading zeros.
Solution
public class StudentCode {
public static void main(String[] args) {
String code = String.format("%04d", 7);
System.out.println("Code: " + code);
}
}Recap: printf = template + specifiers + values
"Hi %s%n"%s %d %f %t %n"Sara"Hi SaraYour turn
Print the name Sara and the age 19 on one line, as in the expected output, then move to a new line. Try it first, then use the hint. Once it passes, try it with your own name and age.
public class AboutMe {
public static void main(String[] args) {
// Print the sentence with printf
}
}My name is Sara and I am 19.
Hint 1
The template is "My name is %s and I am %d.%n".
Solution
public class AboutMe {
public static void main(String[] args) {
System.out.printf("My name is %s and I am %d.%n", "Sara", 19);
}
}Review questions
What happens when System.out.printf("%f", 5); runs?
5 is a whole number and %f needs a decimal. printf does not convert it for you, and the compiler does not read the template. The fix is to write 5.0.Which format prints a name aligned left in 12 columns?
- means align left; without it the value aligns right. Leading zeros are for numbers only.Put it all together. What does the program print?
public class ReviewMix {
public static void main(String[] args) {
System.out.printf("%-6s|%03d|%.1f%%%n", "Sara", 7, 91.25);
}
}Show the output
Sara |007|91.3%
Why? %-6s takes 6 columns on the left, %03d fills with zeros, %.1f rounds to one place, and %% prints %.
What is the difference between printf and String.format?
String.format hands you the text to save or use later.