What is IllegalStateException?

In Java, IllegalStateException is a runtime exception. It signals that a method has been invoked at an illegal or inappropriate time. In other words, the object is not in the correct state for the requested operation. This often happens when you misuse an object based on its lifecycle or state.

Common Causes and Solutions

Let’s explore common scenarios where IllegalStateException occurs and how to fix them.

1. Misusing an Iterator

One of the most frequent causes is calling remove() on an Iterator before calling next().

Problematic Code

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");

        Iterator<String> iterator = list.iterator();
        
        try {
            // Throws IllegalStateException because next() was not called first
            iterator.remove(); 
        } catch (IllegalStateException e) {
            System.err.println("Caught an exception: " + e.getMessage());
        }
    }
}

The remove() method can only be called once per call to next(). Calling it without a preceding next() call throws the exception.

Solution

Always call next() before you call remove(). This positions the iterator on a valid element to be removed.

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorSolution {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");

        Iterator<String> iterator = list.iterator();
        
        if (iterator.hasNext()) {
            iterator.next(); // Move to the first element
            iterator.remove(); // Now it's safe to remove
        }
        
        System.out.println("List after removal: " + list); // Output: [B]
    }
}

2. Operating on a Closed Resource

Attempting to use a resource that has already been closed, like a Scanner or a Stream, can also cause this exception.

Problematic Code

import java.util.Scanner;

public class ScannerExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        scanner.close();
        
        try {
            // Throws IllegalStateException because the scanner is closed
            scanner.nextLine(); 
        } catch (IllegalStateException e) {
            System.err.println("Caught an exception: " + e.getMessage());
        }
    }
}

Once close() is called, the Scanner object is no longer in a state where it can read input.

Solution

Ensure that you perform all necessary operations before closing the resource. Using a try-with-resources block is a best practice to manage resource lifecycles effectively.

import java.util.Scanner;

public class ScannerSolution {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            System.out.print("Enter your name: ");
            String name = scanner.nextLine();
            System.out.println("Hello, " + name);
        } 
        // The scanner is automatically closed here.
        // No further operations are needed.
    }
}

3. Incorrect State in Custom Classes

You might define a class where methods should only be called in a specific order. If the order is violated, you can throw IllegalStateException to enforce the contract.

Problematic Code

public class ConnectionManager {
    private boolean connected = false;

    public void connect() {
        this.connected = true;
        System.out.println("Connected.");
    }

    public void sendData(String data) {
        if (!connected) {
            throw new IllegalStateException("Not connected. Cannot send data.");
        }
        System.out.println("Sending data: " + data);
    }

    public static void main(String[] args) {
        ConnectionManager manager = new ConnectionManager();
        try {
            // Throws IllegalStateException because connect() was not called
            manager.sendData("Hello");
        } catch (IllegalStateException e) {
            System.err.println("Caught an exception: " + e.getMessage());
        }
    }
}

Solution

Always ensure the object is in the correct state before calling its methods. In this case, call connect() before sendData().

public class ConnectionManagerSolution {
    private boolean connected = false;

    public void connect() {
        this.connected = true;
        System.out.println("Connected.");
    }

    public void sendData(String data) {
        if (!connected) {
            throw new IllegalStateException("Not connected. Cannot send data.");
        }
        System.out.println("Sending data: " + data);
    }

    public static void main(String[] args) {
        ConnectionManagerSolution manager = new ConnectionManagerSolution();
        manager.connect(); // Establish the connection first
        manager.sendData("Hello, world!"); // Now it's safe to send data
    }
}

Conclusion

IllegalStateException is a preventative exception. It helps you catch programming errors early by enforcing that methods are used correctly according to the object’s state. To avoid it, always check if an object is in the appropriate state before calling a method that has state-based prerequisites.

Leave a comment