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());
}
}
}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 asIOExceptionwhen 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());
}
}
}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);
}
}
}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());
}
}
}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
- Write
setAge(int age)that throws anIllegalArgumentExceptionfor ages below 0 or above 150, and catch it. - Create an unchecked exception
EmptyNameExceptionand throw it for an empty name. - Make a class that implements
AutoCloseable, use it in try-with-resources and check whencloseruns.