Shiklo Programming
EN
  • English
  • Español
  • Português
  • Deutsch
  • Français
  • 日本語
  • हिन्दी

Java Throw and Throws

In Exceptions you caught exceptions that Java threw. Your own code can throw them too. When a method receives a value it cannot work with, such as a negative amount or an empty name, the clearest reaction is often to throw an exception: the caller then has to deal with the problem instead of silently getting a wrong result.

throw

throw is followed by a new exception object. It stops the method immediately, like return, but the exception travels up to the caller until some catch handles it:

public class Main {
    static double squareRoot(double x) {
        if (x < 0) {
            throw new IllegalArgumentException("Negative number: " + x);
        }
        return Math.sqrt(x);
    }

    public static void main(String[] args) {
        System.out.println(squareRoot(49));
        try {
            System.out.println(squareRoot(-9));
        } catch (IllegalArgumentException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}
Output
7.0
Error: Negative number: -9.0

IllegalArgumentException is the usual choice for a bad parameter, and IllegalStateException for a method called at the wrong time.

Checked and unchecked exceptions

Java has two kinds of exceptions:

  • Unchecked exceptions (subclasses of RuntimeException) are usually programming mistakes: NullPointerException, ArithmeticException, IllegalArgumentException. The compiler does not force you to handle them.
  • Checked exceptions (other subclasses of Exception) are problems a correct program must still expect, mostly from the outside world, such as IOException when a file is missing. The compiler insists that you either catch them or declare them.

A method declares the checked exceptions it may throw with throws in its heading:

public class Main {
    static void checkAge(int age) throws Exception {
        if (age < 18) {
            throw new Exception("Too young: " + age);
        }
        System.out.println("Access granted for age " + age);
    }

    public static void main(String[] args) {
        try {
            checkAge(25);
            checkAge(12);
        } catch (Exception e) {
            System.out.println("Access denied. " + e.getMessage());
        }
    }
}
Output
Access granted for age 25
Access denied. Too young: 12

Remove the try ... catch and the program no longer compiles: the compiler reminds you that checkAge may throw.

Your own exception classes

You can create an exception class by extending Exception (checked) or RuntimeException (unchecked). A good name makes the problem obvious, and the class can carry extra data:

class InsufficientFundsException extends Exception {
    final double missing;

    InsufficientFundsException(double missing) {
        super("Not enough money, missing " + missing);
        this.missing = missing;
    }
}

class Account {
    private double balance = 500;

    void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException(amount - balance);
        }
        balance -= amount;
        System.out.println("Withdrew " + amount + ", left " + balance);
    }
}

public class Main {
    public static void main(String[] args) {
        Account acc = new Account();
        try {
            acc.withdraw(200);
            acc.withdraw(450);
        } catch (InsufficientFundsException e) {
            System.out.println(e.getMessage());
            System.out.println("Please add at least " + e.missing);
        }
    }
}
Output
Withdrew 200.0, left 300.0
Not enough money, missing 150.0
Please add at least 150.0

super(message) passes the message to the Exception constructor, as in Inheritance.

try-with-resources

Objects such as files and scanners must be closed after use. If you create them in brackets after try, Java closes them automatically, even when an exception happens. Any class that implements the AutoCloseable interface can be used this way:

class Connection implements AutoCloseable {
    Connection() {
        System.out.println("Opened");
    }

    void send(String msg) {
        System.out.println("Sent: " + msg);
    }

    @Override
    public void close() {
        System.out.println("Closed");
    }
}

public class Main {
    public static void main(String[] args) {
        try (Connection c = new Connection()) {
            c.send("hello");
            throw new IllegalStateException("network down");
        } catch (IllegalStateException e) {
            System.out.println("Caught: " + e.getMessage());
        }
    }
}
Output
Opened
Sent: hello
Closed
Caught: network down

"Closed" is printed before the catch block runs. You will use try-with-resources for files in Read Files.

Practice exercises

  1. Write setAge(int age) that throws an IllegalArgumentException for ages below 0 or above 150, and catch it.
  2. Create an unchecked exception EmptyNameException and throw it for an empty name.
  3. Make a class that implements AutoCloseable, use it in try-with-resources and check when close runs.