Java Calculator Application
Table of Contents + −
In the last lesson you learned about Java ThreadLocal. Now let’s build something you can run and play with: a console calculator. It touches nearly everything you have learned, and we will grow it one piece at a time.
🎯 The problem we are solving
Picture a tiny on-screen calculator app. It asks “what do you want to do?”, takes two numbers, and prints the result. Doing it well means handling the messy parts.
- The user might pick an option that does not exist.
- They might try to divide by zero.
- They might want many sums in a row without restarting.
So our goal is a calculator that keeps asking, handles bad choices calmly, never crashes on divide-by-zero, and exits only when the user says so.
Here is what our app will let the user do:
- Pick an operation: add, subtract, multiply, divide, or exit.
- Type two numbers.
- See the result.
- Repeat as many times as they like.
- Exit cleanly when done.
We combine building blocks you already know:
- A
Scannerreads input. - A
switchpicks the math. - A loop keeps the menu coming back.
Let’s start with the menu.
🧱 Step 1: show a menu and read the choice
Before any math, the user needs to see their options. This code sets up the Scanner and prints the menu once.
import java.util.Scanner;
public class Calculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in);
System.out.println("--- Simple Calculator ---"); System.out.println("1. Add (+)"); System.out.println("2. Subtract (-)"); System.out.println("3. Multiply (x)"); System.out.println("4. Divide (/)"); System.out.println("5. Exit"); System.out.print("Choose an option: ");
int choice = scanner.nextInt(); System.out.println("You chose: " + choice);
scanner.close(); }}Reading it from the top:
import java.util.Scannerlets us read keyboard input. Without it theScannername is unknown.new Scanner(System.in)creates a reader on the keyboard.System.inis the standard input stream.- The
printlncalls print each menu line. The last usesprint(no line break) so typing sits right after the prompt. scanner.nextInt()waits for a whole number and Enter, then stores it inchoice.scanner.close()releases the scanner when done.
That is the skeleton. Next we make it calculate.
🔢 Step 2: read two numbers
A calculator needs two numbers. We use double instead of int so it handles decimals like 3.5, not just whole numbers. This snippet reads the two values.
System.out.print("Enter first number: ");double a = scanner.nextDouble();
System.out.print("Enter second number: ");double b = scanner.nextDouble();Things to notice:
nextDouble()reads a number that may have a decimal point. WithnextInt(), typing2.5would crash the program.- Short names
aandbare fine. Their job is obvious and they live only a few lines. - The prompts make it clear which number is which.
With the choice variable and the numbers in hand, we can do the math.
🔀 Step 3: pick the math with a switch
The user’s choice (1 to 4) tells us which operation to run. A switch is the cleanest tool. It checks one value against several cases and runs the matching block. This code runs the right calculation.
double result = 0;
switch (choice) { case 1: result = a + b; System.out.println("Result: " + result); break; case 2: result = a - b; System.out.println("Result: " + result); break; case 3: result = a * b; System.out.println("Result: " + result); break; case 4: result = a / b; System.out.println("Result: " + result); break; default: System.out.println("That is not a valid option.");}Walking through it:
switch (choice)jumps to the matchingcase.case 1adds,case 2subtracts,case 3multiplies,case 4divides. Each stores the answer inresultand prints it.- The
breakat the end of each case stops the switch there. Without it, Java falls through and runs the next case too. - The
defaultblock runs when no case matches, like typing9. It prints a friendly message instead of doing nothing.
One problem hides in case 4. If the second number is zero, a / b divides by zero. Let’s fix that next.
🛡️ Step 4: handle divide-by-zero gracefully
Dividing by zero is the classic calculator bug. The fix is the same in both cases: check for zero before dividing.
- Whole-number division by zero throws an
ArithmeticExceptionand crashes. doubledivision does not crash but prints a strange value likeInfinityorNaN.
This version guards the divide case so a zero divisor never reaches the division.
case 4: if (b == 0) { System.out.println("Cannot divide by zero. Try again."); } else { result = a / b; System.out.println("Result: " + result); } break;Why this works:
if (b == 0)checks the second number before any division.- If it is zero, we print a clear message and skip the math. The program stays alive.
- If it is not zero, the
elseblock divides safely and prints the result.
Guarding a risky operation before you run it is the difference between a crash and a program that keeps going. Now let’s make the whole thing repeat.
🔁 Step 5: loop until the user exits
Right now the calculator does one sum and stops. We wrap the menu, input, and switch in a while loop controlled by a boolean flag. When the user picks Exit, we flip the flag and the loop ends. This is the loop structure.
boolean running = true;
while (running) { System.out.println("\n--- Simple Calculator ---"); System.out.println("1. Add (+)"); System.out.println("2. Subtract (-)"); System.out.println("3. Multiply (x)"); System.out.println("4. Divide (/)"); System.out.println("5. Exit"); System.out.print("Choose an option: "); int choice = scanner.nextInt();
if (choice == 5) { running = false; System.out.println("Goodbye!"); continue; }
// read numbers and run the switch here}Reading the loop:
boolean running = true;is a flag that says “keep going”. The loop runs while it staystrue.while (running)checks the flag at the top of every round.- Each round prints the menu fresh. The
\nadds a blank line so rounds do not blur together. - Picking
5setsrunning = false, says goodbye, andcontinues. The flag is nowfalse, so the loop ends. - Any other choice falls through to reading the numbers and running the switch.
Before we assemble the full version, let’s give each operation its own method.
🧩 Step 6: a method per operation (optional but clean)
Inline math in the switch works fine. But one small method per operation reads better and is reusable. Each does one job with a clear name. These four methods replace the inline math.
static double add(double a, double b) { return a + b;}
static double subtract(double a, double b) { return a - b;}
static double multiply(double a, double b) { return a * b;}
static double divide(double a, double b) { return a / b; // caller checks for zero first}A few notes:
- Each method is
staticsomaincan call it without creating an object. - Each takes two
doublevalues and returns adouble. The name makes the call read like English:add(a, b). dividedoes not check for zero itself. We keep that guard in the caller. Both are valid; here we keep methods simple and guard at the call.
Now let’s put everything together.
📦 Step 7: the full program
Here is the complete calculator. It loops the menu, reads a choice and two numbers, runs the right method, guards divide-by-zero, handles bad choices, and exits cleanly.
import java.util.Scanner;
public class Calculator {
static double add(double a, double b) { return a + b; }
static double subtract(double a, double b) { return a - b; }
static double multiply(double a, double b) { return a * b; }
static double divide(double a, double b) { return a / b; }
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); boolean running = true;
while (running) { System.out.println("\n--- Simple Calculator ---"); System.out.println("1. Add (+)"); System.out.println("2. Subtract (-)"); System.out.println("3. Multiply (x)"); System.out.println("4. Divide (/)"); System.out.println("5. Exit"); System.out.print("Choose an option: "); int choice = scanner.nextInt();
if (choice == 5) { running = false; System.out.println("Goodbye!"); continue; }
if (choice < 1 || choice > 4) { System.out.println("That is not a valid option. Try again."); continue; }
System.out.print("Enter first number: "); double a = scanner.nextDouble(); System.out.print("Enter second number: "); double b = scanner.nextDouble();
switch (choice) { case 1: System.out.println("Result: " + add(a, b)); break; case 2: System.out.println("Result: " + subtract(a, b)); break; case 3: System.out.println("Result: " + multiply(a, b)); break; case 4: if (b == 0) { System.out.println("Cannot divide by zero. Try again."); } else { System.out.println("Result: " + divide(a, b)); } break; } }
scanner.close(); }}How it flows:
- The loop keeps the program alive. Each round prints the menu and reads a choice. Exit ends the loop.
- A choice outside 1 to 4 is rejected before we ask for numbers.
- Valid choices read two numbers and run the matching method. Divide checks for zero first.
- Guard order matters: Exit first, then invalid option, then ask for numbers. Cheap checks early means we never read numbers for a choice we will reject.
▶️ Step 8: a sample run
Let’s run it and see the whole thing work: an add, a divide, a divide-by-zero, a bad option, and exit.
Output
--- Simple Calculator ---1. Add (+)2. Subtract (-)3. Multiply (x)4. Divide (/)5. ExitChoose an option: 1Enter first number: 12Enter second number: 8Result: 20.0
--- Simple Calculator ---Choose an option: 4Enter first number: 9Enter second number: 2Result: 4.5
--- Simple Calculator ---Choose an option: 4Enter first number: 7Enter second number: 0Cannot divide by zero. Try again.
--- Simple Calculator ---Choose an option: 9That is not a valid option. Try again.
--- Simple Calculator ---Choose an option: 5Goodbye!Each menu choice runs its own path. The divide-by-zero attempt shows a calm message instead of a crash. The invalid option 9 is rejected without asking for numbers. And 5 exits cleanly.
🛠️ Practice Challenge
Try extending the calculator before checking the answers. Each one builds on the program you just wrote.
Challenge 1: Add a modulus operation (the remainder of a division, using %) as menu option 6.
Challenge 2: Add a power operation that raises the first number to the second (for example 2 to the power 3 is 8).
Challenge 3: Stop the program crashing when the user types text like “abc” instead of a number.
⚠️ Common Mistakes
A few calculator slip-ups to watch for.
- Forgetting
breakin the switch. Withoutbreak, one case runs into the next (“fall through”) and you get the wrong result. Every case needs its ownbreak. - Not guarding divide-by-zero. Whole-number division by zero crashes; decimal division prints
InfinityorNaN. Always check the divisor before dividing. - Reading with
nextInt()for decimals. If users may type3.5, read withnextDouble().nextInt()crashes on a decimal point. - No exit option. A calculator that never stops, or one that quits after a single sum, both frustrate users. Give a clear Exit and loop until they choose it.
- Ignoring bad menu choices. A choice like
9should get a friendly message from adefaultor a range check, not silent nothing.
✅ Best Practices
Habits that make a console calculator clean and reliable.
- Loop with a clear flag. A
boolean runningcontrolled by the Exit option makes the program’s lifetime obvious at a glance. - One method per operation.
add,subtract,multiply, anddivideeach do one job, so the switch stays short and the code reads like English. - Guard risky operations early. Check for divide-by-zero and invalid options before doing the work, so nothing crashes.
- Use
doublefor flexible math. It handles whole numbers and decimals, so the calculator works for2 + 2and2.5 + 1.1alike. - Validate input. Reject out-of-range choices and re-ask on non-number input so a typo never ends the program.
🧩 What You’ve Learned
Nicely done. You built a complete, runnable console calculator from scratch. Let’s recap.
- ✅ A menu loop with a
boolean runningflag keeps the calculator alive until the user exits. - ✅ A
Scannerreads the menu choice and two numbers, usingnextDouble()so decimals work. - ✅ A
switchon the choice picks the right operation, with abreakin every case. - ✅ A divide-by-zero guard checks the divisor first, so the program never crashes.
- ✅ A method per operation (
add,subtract,multiply,divide) keepsmainshort and clear. - ✅ Input validation rejects bad menu choices and, with
hasNextDouble(), survives non-number typing.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Why does each case in the switch need a break?
Why: Without break, control falls through and runs the next case too, giving a wrong result.
- 2
What is the safe way to handle dividing by zero?
Why: Checking the divisor before the division prevents the crash and lets you show a clear message.
- 3
Why read the numbers with nextDouble() instead of nextInt()?
Why: nextDouble() reads decimals, so the calculator works for whole numbers and fractions alike.
- 4
What keeps the calculator running until the user exits?
Why: A while loop checks the running flag each round; picking Exit sets it false and ends the loop.
🚀 What’s Next?
You have the core skills now: input, decisions, loops, and safe guards. Next we level up to a project with real data and CRUD operations, a Student Management System that stores many records and lets you add, view, update, and remove them. Let’s build it.