Java variables exercises — master types, casting and Strings
In the practice article we deliberately triggered the three classic variable surprises in Java. Now it’s time to solve on your own — but with a twist: the exercises here won’t focus on exactly the same things as the practice. Integer division, casting and == will appear, but as tools to solve something, not as the main character. That’s what happens in real exams.
Three levels, three different contexts. Try to solve them before looking at the solution — even if it’s just 10 minutes wrestling with the compiler. That’s where the real learning happens.
Table of Contents
Java variables exercises — Basic Level
Exercise 1 — BMI calculator
Write a program that asks for weight in kg and height in metres, calculates the Body Mass Index and displays the result with its classification. Also include the ideal weight range for that height.
BMI formula: BMI = weight / (height × height)
Expected output with 70 kg and 1.75 m:
=== BMI CALCULATOR === Weight (kg): 70 Height (m): 1.75 --- Result --- BMI: 22.86 Classification: Normal weight Ideal weight: between 56.7 kg and 80.1 kg Healthy range: 18.5 - 24.9 Status: ✓ Your weight is within the healthy range
Classifications:
BMI < 18.5 → Underweight BMI between 18.5-24.9 → Normal weight BMI between 25-29.9 → Overweight BMI >= 30 → Obese
Ideal weight: the range corresponds to BMI 18.5 and 24.9 for that height.
💡 Hints:
height * height— there’s no^operator for powers in Java, that’s bitwise XOR. UseMath.pow(height, 2)or just multiply- Minimum ideal weight is
18.5 * height * height, maximum is24.9 * height * height - Use a chained
if/else iffor classification — notswitch, because you’re comparingdoubleranges
Java variables exercises — Intermediate Level
Exercise 2 — Time converter
Write a program that asks for a total number of seconds and breaks it down into days, hours, minutes and seconds. Also show what percentage it represents of a full day.
Expected output with 90061 seconds:
=== TIME CONVERTER === Total seconds: 90061 --- Breakdown --- 1 day, 1 hour, 1 minute and 1 second --- In detail --- Days: 1 (86400 seconds) Hours: 1 (3600 seconds) Minutes: 1 (60 seconds) Seconds: 1 --- Percentage of a day --- 90061 seconds = 104.24% of a full day (more than one full day)
💡 Hints:
- This exercise is all integer division and modulo — you don’t need any
doubleuntil the percentage at the end - Order matters: first calculate days (
seconds / 86400), then the remainder (% 86400), then hours from that remainder, and so on - For the percentage you need the cast:
(double) seconds / 86400 * 100 - Watch the text: “1 hour” vs “2 hours” — singular and plural change. Use the ternary operator
Java variables exercises — Final Challenge
Exercise 3 — Shop with products
Write a complete program that manages information for three products in a shop. For each product ask for the name, base price and units in stock. The program generates a report with prices including VAT (21%), the total inventory value and the most expensive product.
Expected output:
=== SHOP MANAGEMENT === --- Product 1 --- Name: Laptop Base price (€): 899.99 Stock: 5 --- Product 2 --- Name: Mouse Base price (€): 29.99 Stock: 23 --- Product 3 --- Name: Keyboard Base price (€): 79.99 Stock: 12 ╔═══════════════════════════════════════════════╗ ║ INVENTORY REPORT ║ ╠═══════════════╦═══════════╦════════╦══════════╣ ║ Product ║ Base ║ +VAT ║ Stock ║ ╠═══════════════╬═══════════╬════════╬══════════╣ ║ Laptop ║ 899.99 € ║1088.99€║ 5 ║ ║ Mouse ║ 29.99 € ║ 36.29€║ 23 ║ ║ Keyboard ║ 79.99 € ║ 96.79€║ 12 ║ ╠═══════════════╩═══════════╩════════╩══════════╣ ║ Total inventory value: 6384.88 € ║ ║ Most expensive product (ex VAT): Laptop ║ ║ Cheapest product (ex VAT): Mouse ║ ╚═══════════════════════════════════════════════╝
The total inventory value is the sum of price × stock for each product.
💡 Hints:
- Declare three-element arrays:
String[] names = new String[3],double[] prices = new double[3],int[] stocks = new int[3] - To find the most expensive: start by assuming the first one is the most expensive and loop through the rest comparing
- The inventory value of each product is
prices[i] * stocks[i]— watch out for integer division if you mix types - The
sc.nextLine()cleanup goes aftersc.nextDouble()andsc.nextInt()— you already know why
What’s wrong here?
Before looking at the solutions, these are the most frequent mistakes in this type of exercise. Can you spot the problem in each one?
Error 1
int seconds = 90061;
double percentage = seconds / 86400 * 100;
System.out.printf("%.2f%%%n", percentage);
// Prints: 100.00% instead of 104.24%
See it? seconds / 86400 is integer division — gives 1. Then 1 * 100 = 100.0. The cast must go before:
double percentage = (double) seconds / 86400 * 100; // Now: 104.24%
Error 2
Scanner sc = new Scanner(System.in);
System.out.print("Name: ");
String name = sc.nextLine();
System.out.print("Price: ");
double price = sc.nextDouble();
System.out.print("Category: ");
String category = sc.nextLine(); // ← reads empty string
Missing the sc.nextLine() cleanup after nextDouble(). The fix:
double price = sc.nextDouble(); sc.nextLine(); // ← consume the leftover \n String category = sc.nextLine(); // now waits for user input
Error 3
String cat = sc.nextLine().trim().toLowerCase();
if (cat == "electronics") {
System.out.println("Valid category");
}
// Never enters the if even when you type "electronics"
== compares memory references, not content. Always:
if (cat.equals("electronics")) { // ← correct
Commented solutions
Solution Exercise 1
import java.util.Scanner;
public class BMICalculator {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("=== BMI CALCULATOR ===");
System.out.println();
System.out.print("Weight (kg): ");
double weight = sc.nextDouble();
System.out.print("Height (m): ");
double height = sc.nextDouble();
// BMI formula — note: ^ does NOT mean power in Java, it's XOR
// height * height is the clearest and most direct approach here
// Math.pow(height, 2) also works but is overkill for squaring
double bmi = weight / (height * height);
// Ideal weight range for this height
// We multiply the BMI limits by height², not the other way around
double minWeight = 18.5 * (height * height);
double maxWeight = 24.9 * (height * height);
// Classification — if/else if because we're comparing double ranges
// switch won't work here: it only handles exact values, not ranges
String classification;
if (bmi < 18.5) {
classification = "Underweight";
} else if (bmi < 25.0) {
classification = "Normal weight"; // 18.5 to 24.9
} else if (bmi < 30.0) {
classification = "Overweight"; // 25 to 29.9
} else {
classification = "Obese"; // 30 or above
}
// Clean boolean — easier to read than putting the condition in printf
boolean healthy = (bmi >= 18.5 && bmi < 25.0);
System.out.println();
System.out.println("--- Result ---");
// %.2f for two decimal places — BMI doesn't need more precision
System.out.printf("BMI: %.2f%n", bmi);
System.out.printf("Classification: %s%n", classification);
System.out.printf("Ideal weight: between %.1f kg and %.1f kg%n",
minWeight, maxWeight);
System.out.printf("Healthy range: 18.5 - 24.9%n");
System.out.println();
// Ternary operator here is cleaner than a full if/else
// when the condition is simple, ternary makes the code more readable
System.out.printf("Status: %s%n",
healthy
? "✓ Your weight is within the healthy range"
: "⚠ Your weight is outside the healthy range");
sc.close();
}
}
Solution Exercise 2
import java.util.Scanner;
public class TimeConverter {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("=== TIME CONVERTER ===");
System.out.println();
System.out.print("Total seconds: ");
int totalSeconds = sc.nextInt();
// All integer division and modulo — no doubles until the percentage
// Order matters: always extract the largest unit first
// How many complete days fit?
int days = totalSeconds / 86400; // 86400 = 60*60*24
int remainder = totalSeconds % 86400; // what's left after removing days
// From the remainder, how many complete hours?
int hours = remainder / 3600; // 3600 = 60*60
remainder = remainder % 3600; // reuse the variable
// From what's left, how many complete minutes?
int minutes = remainder / 60;
int seconds = remainder % 60; // what's left are seconds
System.out.println();
System.out.println("--- Breakdown ---");
// Singular/plural with ternary — a small detail that makes a difference
System.out.printf("%d %s, %d %s, %d %s and %d %s%n",
days, (days == 1 ? "day" : "days"),
hours, (hours == 1 ? "hour" : "hours"),
minutes, (minutes == 1 ? "minute" : "minutes"),
seconds, (seconds == 1 ? "second" : "seconds"));
System.out.println();
System.out.println("--- In detail ---");
System.out.printf("Days: %-4d (86400 seconds)%n", days);
System.out.printf("Hours: %-4d (3600 seconds)%n", hours);
System.out.printf("Minutes: %-4d (60 seconds)%n", minutes);
System.out.printf("Seconds: %d%n", seconds);
System.out.println();
System.out.println("--- Percentage of a day ---");
// Now we need double — and the cast goes BEFORE dividing
// If we wrote totalSeconds / 86400 * 100, integer division would
// truncate the result before the double ever comes into play
double percentage = (double) totalSeconds / 86400 * 100;
System.out.printf("%d seconds = %.2f%% of a full day%n",
totalSeconds, percentage);
// Additional message based on result
if (percentage > 100) {
System.out.println("(more than one full day)");
} else if (percentage == 100) {
System.out.println("(exactly one full day)");
} else {
System.out.printf("(%.2f%% remaining to complete the day)%n",
100 - percentage);
}
sc.close();
}
}
Solution Exercise 3
import java.util.Scanner;
public class ShopManagement {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("=== SHOP MANAGEMENT ===");
System.out.println();
// Arrays for the three products — same index = same product
// Fixed size because we know there are exactly 3 products
int numProducts = 3;
String[] names = new String[numProducts];
double[] prices = new double[numProducts];
int[] stocks = new int[numProducts];
// Collect data for each product with a loop
// i goes from 0 to 2 — arrays in Java start at 0, not 1
for (int i = 0; i < numProducts; i++) {
System.out.printf("--- Product %d ---%n", i + 1); // show 1,2,3 to user
System.out.print("Name: ");
names[i] = sc.nextLine();
System.out.print("Base price (€): ");
prices[i] = sc.nextDouble();
sc.nextLine(); // clean up the \n — you know why
System.out.print("Stock: ");
stocks[i] = sc.nextInt();
sc.nextLine(); // another leftover \n
System.out.println();
}
// Calculate VAT and inventory value for each product
double VAT = 0.21;
double[] pricesWithVAT = new double[numProducts];
double[] inventoryValues = new double[numProducts];
double totalInventory = 0;
for (int i = 0; i < numProducts; i++) {
pricesWithVAT[i] = prices[i] * (1 + VAT);
// stocks[i] is int, prices[i] is double
// int * double gives double automatically — widening
inventoryValues[i] = prices[i] * stocks[i];
totalInventory += inventoryValues[i];
}
// Find most expensive and cheapest
// Strategy: start by assuming the first one is the extreme
// then loop through the rest to see if any is larger/smaller
int indexMostExpensive = 0;
int indexCheapest = 0;
for (int i = 1; i < numProducts; i++) {
if (prices[i] > prices[indexMostExpensive]) {
indexMostExpensive = i; // found a more expensive one
}
if (prices[i] < prices[indexCheapest]) {
indexCheapest = i; // found a cheaper one
}
}
// Display formatted report
System.out.println("╔═══════════════════════════════════════════════╗");
System.out.println("║ INVENTORY REPORT ║");
System.out.println("╠═══════════════╦═══════════╦════════╦══════════╣");
System.out.println("║ Product ║ Base ║ +VAT ║ Stock ║");
System.out.println("╠═══════════════╬═══════════╬════════╬══════════╣");
for (int i = 0; i < numProducts; i++) {
// %-13s left-aligns with 13 chars — names stay aligned
System.out.printf("║ %-13s ║ %7.2f € ║%6.2f€║ %8d ║%n",
names[i], prices[i], pricesWithVAT[i], stocks[i]);
}
System.out.println("╠═══════════════╩═══════════╩════════╩══════════╣");
System.out.printf( "║ Total inventory value: %12.2f € ║%n",
totalInventory);
System.out.printf( "║ Most expensive (ex VAT): %-14s ║%n",
names[indexMostExpensive]);
System.out.printf( "║ Cheapest (ex VAT): %-14s ║%n",
names[indexCheapest]);
System.out.println("╚═══════════════════════════════════════════════╝");
sc.close();
}
}
Visualise with Python Tutor
Select Java from the dropdown and paste in pythontutor.com:
public class Demo {
public static void main(String[] args) {
// Integer division vs correct cast
int seconds = 90061;
// WRONG — integer division before cast
double wrongPercentage = seconds / 86400 * 100;
// RIGHT — cast before dividing
double rightPercentage = (double) seconds / 86400 * 100;
System.out.printf("Wrong: %.2f%%%n", wrongPercentage);
System.out.printf("Right: %.2f%%%n", rightPercentage);
// Finding the maximum in an array
double[] prices = {899.99, 29.99, 79.99};
int indexMostExpensive = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[indexMostExpensive]) {
indexMostExpensive = i;
}
}
System.out.println("Most expensive at index: " + indexMostExpensive);
System.out.println("Price: " + prices[indexMostExpensive]);
}
}
Step through and observe two key moments. When seconds / 86400 * 100 is evaluated, Python Tutor shows that seconds / 86400 gives 1 — integer — before the result is assigned to the double. The damage is already done. In the second version, the cast converts seconds to 104156.0 before dividing and everything flows as decimal. In the array search loop, watch how indexMostExpensive starts at 0 and only changes when a higher price is found — at the end it points to the correct index without needing to store the maximum price separately.
Cheat sheet — Java variables
// ============================================
// CHEAT SHEET — Java Variables
// Sergio Learns · sergiolearns.com
// ============================================
// PRIMITIVE TYPES — the ones you'll use in FP2
int i = 42; // integers — most common
double d = 3.14; // decimals — always double, not float
boolean b = true; // true or false — lowercase
char c = 'A'; // one character — single quotes
// CONSTANTS — cannot change after assignment
final double PI = 3.14159;
final int MAX_ITEMS = 100;
// STRING — class, not primitive
String s = "hello";
// Most used methods:
s.length() // length
s.charAt(0) // character at position 0
s.toUpperCase() // all uppercase
s.toLowerCase() // all lowercase
s.trim() // removes leading/trailing spaces
s.equals("hello") // compare content — ALWAYS this
s.equalsIgnoreCase("HELLO") // same but ignores case
// THE GOLDEN RULE FOR STRINGS
s1.equals(s2) // ← CORRECT — compares content
s1 == s2 // ← DANGEROUS — compares memory references
// WIDENING — automatic, smaller to larger type
int → long → double // Java does it automatically
// NARROWING — manual, larger to smaller — may lose data
double d = 9.99;
int i = (int) d; // → 9 (truncates, does NOT round)
// To round: (int) Math.round(d) → 10
// THE INTEGER DIVISION TRAP
int a = 7, b = 2;
int wrong = a / b; // → 3 (integer)
double right = (double) a / b; // → 3.5 (cast BEFORE)
double trap = (double)(a / b); // → 3.0 (cast AFTER — too late)
// MODULO AND INTEGER DIVISION — very useful together
int total = 90061;
int days = total / 86400; // how many complete days
int remainder = total % 86400; // what's left after removing days
int hours = remainder / 3600;
// ... and so on down to seconds
// SCANNER — nextLine() trap after nextInt/nextDouble
int age = sc.nextInt();
sc.nextLine(); // ← ALWAYS after nextInt/nextDouble
String name = sc.nextLine(); // without the line above, this reads ""
// LIMIT VALUES — useful for detecting overflow
Integer.MAX_VALUE // 2,147,483,647 — max int
Integer.MIN_VALUE // -2,147,483,648 — min int
Double.MAX_VALUE // largest positive double
// TERNARY OPERATOR — for simple one-line conditions
String text = (condition) ? "value if true" : "value if false";
// Example:
String plural = (days == 1) ? "day" : "days";
// PRINTF — most used specifiers
%d → int
%f → double (%.2f = 2 decimal places)
%s → String
%c → char
%b → boolean
%n → newline in printf
%% → literal %
%10d → right-aligned, 10 chars wide
%-10s → left-aligned, 10 chars wide
// MATH — most used functions
Math.abs(x) // absolute value
Math.pow(x, 2) // x to the power of 2
Math.sqrt(x) // square root
Math.round(x) // round to nearest integer
Math.max(a, b) // larger of two values
Math.min(a, b) // smaller of two values
Keep goingAll Java (en) articles
One Comment