← Back to Week 2 Hub

Common Errors Guide

The mistakes everyone makes in Week 2 — and how to fix them

String Errors
#1 Using == to compare Strings Use .equals() instead of ==
What you wrote:
String color = scanner.nextLine(); if (color == "red") { System.out.println("You picked red!"); }
What happens: The condition is false even when the user types "red". The if-block never executes, and nothing prints.
The fix:
String color = scanner.nextLine(); if (color.equals("red")) { System.out.println("You picked red!"); }
Why: The == operator checks if two variables point to the same object in memory, not whether the text matches. The .equals() method compares the actual content character by character. Always use .equals() or .equalsIgnoreCase() when comparing Strings.
#2 StringIndexOutOfBoundsException charAt() or substring() with invalid index
What you wrote:
String word = "Java"; char last = word.charAt(4); // index 4 does not exist!
What happens: Runtime crash:
java.lang.StringIndexOutOfBoundsException: String index out of range: 4
The program terminates immediately.
The fix:
String word = "Java"; char last = word.charAt(word.length() - 1); // index 3 = 'a'
Why: String indexes start at 0, so "Java" has indexes 0 through 3. Calling charAt(4) asks for a position that does not exist. The last valid index is always length() - 1. The same rule applies to substring() — always check your index math against the string's length.
#3 substring() end index is exclusive Off-by-one with substring boundaries
What you wrote:
String message = "Welcome"; // Trying to get "Wel" (first 3 characters) String part = message.substring(0, 2); System.out.println(part); // prints "We" — only 2 chars!
What happens: You expected "Wel" but got "We". The end index is exclusive, meaning the character at that index is NOT included.
The fix:
String message = "Welcome"; String part = message.substring(0, 3); // includes index 0, 1, 2 System.out.println(part); // prints "Wel"
Why: substring(start, end) returns characters from index start up to but not including index end. Think of it as: the number of characters you get is end - start. So substring(0, 3) gives you 3 characters starting at index 0.
#4 NumberFormatException with parseInt Parsing a non-numeric string as a number
What you wrote:
String input = "twelve"; int value = Integer.parseInt(input);
What happens: Runtime crash:
java.lang.NumberFormatException: For input string: "twelve"
The program terminates because "twelve" cannot be converted to an integer.
The fix:
// Make sure the string contains only digits String input = "12"; int value = Integer.parseInt(input); // works: value is 12
Why: Integer.parseInt() expects a string that contains only numeric characters (and optionally a leading minus sign). If the string has letters, spaces, decimals, or any non-digit character, Java cannot convert it and throws a NumberFormatException. Always ensure your string is actually a number before parsing.
#5 Forgetting to trim() user input before parsing Hidden spaces cause parse failures
What you wrote:
System.out.println("Enter a number:"); String input = scanner.nextLine(); int number = Integer.parseInt(input); // user typed " 42 " with spaces!
What happens: Runtime crash:
java.lang.NumberFormatException: For input string: " 42 "
The leading and trailing spaces make it fail, even though the number itself is valid.
The fix:
System.out.println("Enter a number:"); String input = scanner.nextLine().trim(); // removes leading/trailing spaces int number = Integer.parseInt(input); // now works with " 42 "
Why: Users often accidentally type extra spaces before or after their input. Integer.parseInt() is strict — it will not ignore whitespace. Calling .trim() on the string first removes any leading and trailing spaces, making the parse succeed.
OOP Errors
#6 Accessing private fields directly Use getters and setters instead
What you wrote:
Vehicle car = new Vehicle("Honda", 2024); System.out.println(car.brand); // trying to access private field!
What happens: Compiler error:
java: brand has private access in Vehicle
The code will not compile because brand is declared as private in the Vehicle class.
The fix:
Vehicle car = new Vehicle("Honda", 2024); System.out.println(car.getBrand()); // use the getter method
Why: When a field is declared private, it can only be accessed from inside that class. This is called encapsulation — one of the core principles of OOP. To read or change private fields from outside the class, use the public getter and setter methods (like getBrand() and setBrand()).
#7 Forgetting the new keyword NullPointerException from uninitialized object
What you wrote:
Product item; System.out.println(item.getPrice()); // item was never created!
What happens: Compiler error (local variable):
java: variable item might not have been initialized
If the variable is a field (instance variable), it defaults to null and you get a NullPointerException at runtime.
The fix:
Product item = new Product("Laptop", 999.99); System.out.println(item.getPrice()); // now item exists
Why: Declaring a variable like Product item; only creates a reference (a label). It does not create an actual object in memory. You must use new to call the constructor and create a real object. Without new, the variable is either uninitialized (compiler error) or null (runtime NullPointerException when you try to use it).
#8 Adding void to a constructor Constructor becomes a regular method
What you wrote:
public class Book { private String title; public void Book(String title) { // void makes this a METHOD, not a constructor! this.title = title; } }
What happens: Java treats this as a regular method named Book, not a constructor. When you write new Book("Moby Dick"), the default (empty) constructor runs instead, and title stays null.
The fix:
public class Book { private String title; public Book(String title) { // no return type — this is a real constructor this.title = title; } }
Why: Constructors are special — they have the same name as the class and no return type (not even void). If you add void (or any return type), Java thinks it is a regular method that happens to share the class name. Remove the return type to make it a proper constructor.
#9 Forgetting this. in constructor or setter Parameter shadows the field
What you wrote:
public class Student { private String name; public Student(String name) { name = name; // assigns the parameter to itself! } }
What happens: No error — the code compiles fine. But name on both sides refers to the parameter, not the field. The field this.name stays null. Later, getName() returns null.
The fix:
public class Student { private String name; public Student(String name) { this.name = name; // this.name = the field, name = the parameter } }
Why: When a parameter has the same name as a field, the parameter shadows the field inside that method. Writing name = name just assigns the parameter to itself — the field is untouched. Use this.name to explicitly refer to the field. This is the most common cause of fields staying null after construction.
Loop Errors
#10 Off-by-one with array length Using <= instead of < in loop condition
What you wrote:
int[] scores = {85, 92, 78, 90, 88}; for (int i = 0; i <= scores.length; i++) { // <= is wrong! System.out.println(scores[i]); }
What happens: The loop runs one extra time. On the last iteration, i equals 5 (the length), and
ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
The fix:
int[] scores = {85, 92, 78, 90, 88}; for (int i = 0; i < scores.length; i++) { // strictly less than System.out.println(scores[i]); }
Why: Arrays are zero-indexed. An array of length 5 has valid indexes 0 through 4. Using <= in the condition means the loop runs when i equals 5, which is out of bounds. Always use < (strictly less than) with .length. This is one of the most common bugs in programming, called an "off-by-one error."
#11 Infinite loop — forgetting to update counter While loop runs forever
What you wrote:
int count = 0; while (count < 5) { System.out.println("Count: " + count); // forgot to increment count! }
What happens: The program prints "Count: 0" forever and never stops. The condition count < 5 is always true because count never changes. You must force-stop the program.
The fix:
int count = 0; while (count < 5) { System.out.println("Count: " + count); count++; // increment so the loop eventually ends }
Why: A while loop keeps running as long as its condition is true. If nothing inside the loop changes the variable in the condition, the condition never becomes false, and the loop runs forever. Always make sure something inside the loop moves you closer to the exit condition.
#12 Semicolon after for loop header Loop body never executes inside the loop
What you wrote:
for (int i = 0; i < 5; i++); // sneaky semicolon! { System.out.println("Iteration: " + i); }
What happens: The loop runs 5 times but does nothing each time (the semicolon creates an empty body). The println block runs only once after the loop finishes. Depending on scope, i may also cause a compiler error.
The fix:
for (int i = 0; i < 5; i++) { // no semicolon here System.out.println("Iteration: " + i); }
Why: A semicolon right after for(...) terminates the loop's body immediately. Java reads it as: "loop 5 times, doing nothing each time." The curly braces below become a separate block that runs once. This is a very subtle bug because the code looks correct at a glance. Always check that there is no ; between the ) and the {.
Array Errors
#13 ArrayIndexOutOfBoundsException Accessing index equal to array length
What you wrote:
String[] fruits = {"Apple", "Banana", "Cherry"}; System.out.println(fruits[3]); // index 3 does not exist!
What happens: Runtime crash:
ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
The array has 3 elements but valid indexes are 0, 1, and 2 only.
The fix:
String[] fruits = {"Apple", "Banana", "Cherry"}; System.out.println(fruits[2]); // last valid index is length - 1 // Or safely get the last element: System.out.println(fruits[fruits.length - 1]); // "Cherry"
Why: Array indexes start at 0. An array of length 3 has indexes 0, 1, and 2. Index 3 is one past the end. The last valid index is always length - 1. This is the same zero-indexing rule as Strings.
#14 Assigning array with = does not copy it Both variables share the same array
What you wrote:
int[] original = {10, 20, 30}; int[] backup = original; // this does NOT copy! backup[0] = 999; System.out.println(original[0]); // prints 999 — original changed too!
What happens: Changing backup[0] also changes original[0]. Both variables point to the exact same array in memory. Your "backup" is not a separate copy.
The fix:
int[] original = {10, 20, 30}; // Option 1: Manual copy with a loop int[] backup = new int[original.length]; for (int i = 0; i < original.length; i++) { backup[i] = original[i]; } // Option 2: Use Arrays.copyOf int[] backup = Arrays.copyOf(original, original.length); backup[0] = 999; System.out.println(original[0]); // prints 10 — original is unchanged
Why: Arrays are reference types in Java. When you write backup = original, you copy the reference (the memory address), not the data. Both variables now point to the same array. To create an independent copy, you must copy each element into a new array.
#15 Forgetting array default values new int[5] fills with 0, not "empty"
What you wrote:
int[] temps = new int[7]; // Only fill in 3 days temps[0] = 72; temps[1] = 68; temps[2] = 75; // Calculate average of all 7 int sum = 0; for (int t : temps) { sum += t; } double avg = (double) sum / temps.length; System.out.println("Average: " + avg); // wrong — includes four 0s!
What happens: The average is 30.71 instead of 71.67. The unfilled slots contain 0 (not "nothing"), and those zeros drag down the average.
The fix:
// Option 1: Only create the size you need int[] temps = {72, 68, 75}; // Option 2: Track how many slots are actually filled int[] temps = new int[7]; int filled = 0; temps[filled++] = 72; temps[filled++] = 68; temps[filled++] = 75; int sum = 0; for (int i = 0; i < filled; i++) { sum += temps[i]; } double avg = (double) sum / filled; // divide by filled, not length
Why: When you create an array with new int[7], Java fills every slot with the default value for that type: 0 for int, 0.0 for double, false for boolean, and null for objects. These slots are not "empty" — they contain real values that will affect calculations. Always be aware of which slots you have actually filled.

Click any error to expand it. These are the most common mistakes from Week 2 exercises.

← Glossary / Key Terms Debugger Guide →