Skip to content

Java Arrays — Find the Bug

Find and fix the bugs in each code snippet. Each exercise has exactly one (or more) bugs. Try to find them before looking at the answer.


Scoring

Difficulty Points per bug
Easy 1 point
Medium 2 points
Hard 3 points

Total possible: 28 points

Score Level
0-8 Beginner — review array basics
9-16 Intermediate — good foundation
17-23 Advanced — strong understanding
24-28 Expert — you know arrays deeply

Easy Bugs (3)

Bug 1: Array Initialization

public class Bug1 {
    public static void main(String[] args) {
        int[] numbers;
        numbers[0] = 42;
        System.out.println(numbers[0]);
    }
}
Hint Is the array actually created, or just declared?
Answer **Bug:** The array is declared but never initialized. `int[] numbers;` only creates a reference variable — no array object exists. **Error:** Compilation error: "variable numbers might not have been initialized" **Fix:**
public class Bug1 {
    public static void main(String[] args) {
        int[] numbers = new int[1]; // allocate the array
        numbers[0] = 42;
        System.out.println(numbers[0]);
    }
}

Bug 2: Off-By-One Error

public class Bug2 {
    public static void main(String[] args) {
        int[] data = {10, 20, 30, 40, 50};

        for (int i = 0; i <= data.length; i++) {
            System.out.println("Element " + i + ": " + data[i]);
        }
    }
}
Hint What is the last valid index for an array of length 5?
Answer **Bug:** The loop condition uses `<=` instead of `<`. When `i == 5`, `data[5]` throws `ArrayIndexOutOfBoundsException` because valid indices are 0-4. **Fix:**
for (int i = 0; i < data.length; i++) { // use < not <=
    System.out.println("Element " + i + ": " + data[i]);
}

Bug 3: Printing an Array

import java.util.Arrays;

public class Bug3 {
    public static void main(String[] args) {
        int[] scores = {95, 87, 73, 91, 68};

        System.out.println("Scores: " + scores);
        System.out.println("Equal? " + scores.equals(new int[]{95, 87, 73, 91, 68}));
    }
}
Hint What does `toString()` and `equals()` do on arrays?
Answer **Bugs (2):** 1. `scores` in string concatenation calls `Object.toString()` which prints something like `[I@15db9742` instead of the contents. 2. `scores.equals()` uses `Object.equals()` which compares references, not contents. Returns `false`. **Fix:**
System.out.println("Scores: " + Arrays.toString(scores));
System.out.println("Equal? " + Arrays.equals(scores, new int[]{95, 87, 73, 91, 68}));

Medium Bugs (4)

Bug 4: Array Copy Aliasing

public class Bug4 {
    public static void main(String[] args) {
        int[] original = {1, 2, 3, 4, 5};
        int[] backup = original; // "backup" the array

        // Modify original
        original[0] = 999;

        System.out.println("Original[0]: " + original[0]); // 999
        System.out.println("Backup[0]: " + backup[0]);     // expected: 1
    }
}
Hint Does `int[] backup = original` create a copy or an alias?
Answer **Bug:** `int[] backup = original` copies the **reference**, not the array. Both variables point to the same array object. Modifying one modifies the other. **Fix:**
int[] backup = Arrays.copyOf(original, original.length); // or original.clone()

Bug 5: Sorting and Searching

import java.util.Arrays;

public class Bug5 {
    public static void main(String[] args) {
        int[] data = {42, 17, 93, 5, 68, 31};

        // Search for 42
        int index = Arrays.binarySearch(data, 42);
        System.out.println("42 found at index: " + index);
    }
}
Hint What is the prerequisite for `Arrays.binarySearch()`?
Answer **Bug:** `Arrays.binarySearch()` requires the array to be **sorted first**. The array `{42, 17, 93, 5, 68, 31}` is not sorted. The result is undefined (may return incorrect index or negative value). **Fix:**
int[] data = {42, 17, 93, 5, 68, 31};
Arrays.sort(data); // MUST sort first
int index = Arrays.binarySearch(data, 42);
System.out.println("42 found at index: " + index);

Bug 6: For-Each Modification

public class Bug6 {
    public static void main(String[] args) {
        int[] prices = {100, 200, 300, 400, 500};

        // Apply 10% discount
        for (int price : prices) {
            price = (int)(price * 0.9);
        }

        // Print discounted prices
        for (int price : prices) {
            System.out.println(price);
        }
    }
}
Hint Does the for-each variable modify the original array element?
Answer **Bug:** The for-each loop variable `price` is a **copy** of the array element. Modifying `price` does not modify `prices[i]`. The array remains unchanged. **Output:** 100, 200, 300, 400, 500 (no discount applied) **Fix:**
for (int i = 0; i < prices.length; i++) {
    prices[i] = (int)(prices[i] * 0.9);
}

Bug 7: 2D Array Initialization

public class Bug7 {
    public static void main(String[] args) {
        int[][] matrix = new int[3][];

        // Fill with identity matrix
        for (int i = 0; i < 3; i++) {
            matrix[i][i] = 1;
        }

        // Print
        for (int[] row : matrix) {
            for (int val : row) {
                System.out.print(val + " ");
            }
            System.out.println();
        }
    }
}
Hint When you create `new int[3][]`, what are the inner arrays initialized to?
Answer **Bug:** `new int[3][]` creates an array of 3 `null` references. The inner arrays are never created. Accessing `matrix[i][i]` throws `NullPointerException`. **Fix:**
int[][] matrix = new int[3][];

// Initialize inner arrays first
for (int i = 0; i < 3; i++) {
    matrix[i] = new int[3]; // create each row
}

// Now fill
for (int i = 0; i < 3; i++) {
    matrix[i][i] = 1;
}
Or simply: `int[][] matrix = new int[3][3];` creates all inner arrays automatically.

Hard Bugs (3)

Bug 8: Array Covariance Trap

public class Bug8 {
    public static void fillWithDefaults(Object[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new Object(); // fill with default objects
        }
    }

    public static void main(String[] args) {
        String[] names = new String[5];
        fillWithDefaults(names); // should fill with defaults

        for (String name : names) {
            System.out.println(name.toUpperCase());
        }
    }
}
Hint Can you store an `Object` into a `String[]` even when accessed through an `Object[]` reference?
Answer **Bug:** `fillWithDefaults` stores `Object` instances into what is actually a `String[]` (passed as `Object[]` due to array covariance). This throws `ArrayStoreException` at runtime because `Object` is not a `String`. **Fix (option 1):** Store the correct type:
public static void fillWithDefaults(Object[] arr) {
    for (int i = 0; i < arr.length; i++) {
        arr[i] = ""; // empty string, compatible with String[]
    }
}
**Fix (option 2):** Use generics:
public static <T> void fillWithDefaults(T[] arr, T defaultValue) {
    Arrays.fill(arr, defaultValue);
}

// Usage:
fillWithDefaults(names, "unknown");

Bug 9: Arrays.asList Primitive Trap

import java.util.Arrays;
import java.util.List;

public class Bug9 {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        List<Integer> list = Arrays.asList(numbers);

        System.out.println("Size: " + list.size());
        System.out.println("Contains 3? " + list.contains(3));

        // Remove element
        list.remove(0);
        System.out.println("After remove: " + list);
    }
}
Hint How does `Arrays.asList` handle primitive arrays? And can you structurally modify the returned list?
Answer **Bugs (3):** 1. **Compilation error:** `Arrays.asList(int[])` returns `List`, not `List`. Cannot assign to `List`. 2. **Size is 1, not 5:** Even if you fix the type, `Arrays.asList(numbers)` treats `int[]` as a single `Object`, not 5 individual integers. 3. **`list.remove(0)` throws `UnsupportedOperationException`:** The list returned by `Arrays.asList` is fixed-size. **Fix:**
int[] numbers = {1, 2, 3, 4, 5};

// Convert properly
List<Integer> list = new ArrayList<>(
    Arrays.stream(numbers).boxed().collect(Collectors.toList())
);

System.out.println("Size: " + list.size());       // 5
System.out.println("Contains 3? " + list.contains(3)); // true
list.remove(0);
System.out.println("After remove: " + list);       // [2, 3, 4, 5]

Bug 10: Concurrent Array Modification

import java.util.Arrays;

public class Bug10 {
    private static int[] sharedData = {0, 0, 0, 0, 0};
    private static boolean ready = false;

    public static void main(String[] args) throws InterruptedException {
        Thread writer = new Thread(() -> {
            for (int i = 0; i < sharedData.length; i++) {
                sharedData[i] = i + 1;
            }
            ready = true;
        });

        Thread reader = new Thread(() -> {
            while (!ready) {
                Thread.yield();
            }
            // At this point, writer is done, so all values should be set
            int sum = 0;
            for (int val : sharedData) {
                sum += val;
            }
            System.out.println("Sum: " + sum); // expected: 15
        });

        reader.start();
        writer.start();
        reader.join();
        writer.join();
    }
}
Hint Are the array writes and the `ready` flag visible across threads? Consider the Java Memory Model.
Answer **Bugs (2):** 1. **`ready` is not `volatile`:** The reader thread may never see `ready = true` because there is no happens-before relationship. The loop could run forever (or be optimized away by JIT). 2. **Array elements have no visibility guarantee:** Even if `ready` becomes visible, the array writes (`sharedData[i] = i + 1`) may not be visible to the reader thread. The reader could see stale values (all zeros or partial writes). **Fix:**
private static volatile int[] sharedData = {0, 0, 0, 0, 0};
private static volatile boolean ready = false;

// Or better: use AtomicIntegerArray
private static AtomicIntegerArray sharedData = new AtomicIntegerArray(5);

// Or best: use proper synchronization
private static final Object lock = new Object();
Making `ready` volatile establishes a happens-before edge: all writes before `ready = true` are visible after reading `ready == true`. But the cleanest solution uses `AtomicIntegerArray` or explicit synchronization.

Bug 11: Deep Copy vs Shallow Copy

import java.util.Arrays;

public class Bug11 {
    public static void main(String[] args) {
        int[][] original = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        int[][] copy = original.clone(); // "deep copy"

        // Modify copy
        copy[0][0] = 999;

        // Check original
        System.out.println("Original[0][0]: " + original[0][0]);
        // Expected: 1, but prints 999!
    }
}
Hint Does `clone()` perform a deep copy or a shallow copy for 2D arrays?
Answer **Bug:** `clone()` on a 2D array creates a **shallow copy** — the outer array is new, but the inner arrays are shared references. `copy[0]` and `original[0]` point to the same `int[]` object. **Fix — deep copy:**
int[][] copy = new int[original.length][];
for (int i = 0; i < original.length; i++) {
    copy[i] = Arrays.copyOf(original[i], original[i].length);
}
Or using streams:
int[][] copy = Arrays.stream(original)
    .map(int[]::clone)
    .toArray(int[][]::new);

Bug 12: Generic Array Creation

public class Bug12<T> {
    private T[] items;

    public Bug12(int capacity) {
        items = new T[capacity]; // create generic array
    }

    public void set(int index, T item) {
        items[index] = item;
    }

    public T get(int index) {
        return items[index];
    }

    public static void main(String[] args) {
        Bug12<String> container = new Bug12<>(10);
        container.set(0, "hello");
        System.out.println(container.get(0));
    }
}
Hint Can you create a generic array with `new T[size]` in Java?
Answer **Bug:** `new T[capacity]` is illegal in Java. Due to type erasure, `T` is erased to `Object` at runtime, and the JVM cannot verify the array type. This is a compilation error. **Fix:**
public class Bug12<T> {
    private Object[] items; // use Object[] internally

    public Bug12(int capacity) {
        items = new Object[capacity];
    }

    public void set(int index, T item) {
        items[index] = item;
    }

    @SuppressWarnings("unchecked")
    public T get(int index) {
        return (T) items[index]; // unchecked cast
    }

    public static void main(String[] args) {
        Bug12<String> container = new Bug12<>(10);
        container.set(0, "hello");
        System.out.println(container.get(0)); // hello
    }
}
This is exactly how `ArrayList` is implemented internally.

Score Card

Bug # Difficulty Points Found?
1 Easy 1
2 Easy 1
3 Easy 2 (2 bugs)
4 Medium 2
5 Medium 2
6 Medium 2
7 Medium 2
8 Hard 3
9 Hard 3 (3 bugs)
10 Hard 3 (2 bugs)
11 Hard 3
12 Hard 3
Total 28