Exceptions and Assertions
Definition
An exception represents an error condition that can occur during the normal course of program execution. When an exception occurs, or is thrown, the normal sequence of flow is terminated. The exception-handling routine is then executed; we say the thrown exception is caught.
Not Catching Exceptions
Scanner scanner = new Scanner(System.in);
System.out.println("Enter integer:");
int number = scanner.nextInt();
Error message for invalid input:
/* Exception in thread "main" java.lang.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:819)
at java.util.Scanner.next(Scanner.java:1431)
at java.util.Scanner.nextInt(Scanner.java:2040)
at java.util.Scanner.nextInt(Scanner.java:2000)
at Ch8Sample1.main(Ch8Sample1.java:35)
Error message for invalid input */
Catching an Exception
System.out.print(prompt);
try {
age = scanner.nextInt();
} catch (InputMismatchException e){
System.out.println("Invalid Entry. " + "Please enter digits only");
}
// AgeInputVer2.java
Let’s modify the getAge method in AgeInputVer1 so that it will loop until a valid input is entered (int value).
Output:
How old are you? 12a
Invalid Entry. Please enter digits only.
How old are you? 12
Already had your birthday this year? (Y or N)Y
You are born in 2008
Getting Information
There are two methods we can call to get information about the thrown exception:
getMessageprintStackTrace
try {
// ...
} catch (InputMismatchException e){
scanner.next(); // remove the leftover garbage char
System.out.println(e.getMessage());
e.printStackTrace();
}
Quick Check
What will be displayed on the console window when the following code is executed, and the user enters abc123 and 14?
Scanner scanner = new Scanner(System.in);
try {
int num1 = scanner.nextInt();
System.out.println("Input 1 accepted");
int num2 = scanner.nextInt();
System.out.println("Input 2 accepted");
} catch (InputMismatchException e) {
System.out.println("Invalid Entry");
}
If the user enters abc123 and 14 as input, the code will catch the InputMismatchException for the first input attempt (abc123). The catch block will be executed, and “Invalid Entry” will be displayed on the console. The program will not proceed to the second input.
So, the expected output on the console will be:
Invalid Entry
Multiple catch Blocks
A single try-catch statement can include multiple catch blocks, one for each type of exception.
while (true) {
System.out.print(prompt);
try {
age = scanner.nextInt();
if (age < 0) {
throw new Exception("Negative age is invalid");
}
return age; // input okay so return the value & exit
} catch (InputMismatchException e) {
scanner.next();
System.out.println("Input is invalid.\n" + "Please enter digits only");
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
Exception Types
All types of thrown errors are instances of the Throwable class or its subclasses. Serious errors are represented by instances of the Error class or its subclasses, while exceptional cases that common applications should handle are represented by instances of the Exception class or its subclasses.
Throwable Hierarchy
There are over 60 classes in the Throwable hierarchy.
import java.util.InputMismatchException;
import java.util.Scanner;
public class BasicExceptionHandling {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
int num = scanner.nextInt();
if (num != 0) {
throw new Exception("Not zero");
}
System.out.println("I'm happy with the input.");
} catch (InputMismatchException e) {
System.out.println("Invalid Entry");
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output Analysis:
- For input -1: “Error: Not zero” (due to the exception thrown for
num != 0) - For input 0: “I’m happy with the input.”
- For input “12XY”: “Invalid Entry” (due to
InputMismatchException)
Multiple Catch Blocks
- Only one catch block is executed at a time.
- Must be ordered from most specific to most general.
try {
// ...
} catch (Exception e) {
// ...
} catch (InputMismatchException e) {
// ...
}
Importance of Order
If catch blocks are reversed, the second catch block will never be executed because any exception object that is an instance of Exception or its subclasses will match the first catch block.
The Finally Block
Purpose
In situations where certain actions must be taken regardless of whether an exception is thrown or not, use the finally block.
Example
try {
// ...
} catch (InputMismatchException e) {
// ...
} catch (Exception e) {
// ...
} finally {
System.out.println("DONE");
}
Throwing Exceptions
throw and throws Clause
throw: Create a new instance of an exception or its subclasses.throws: Explicitly specify the exceptions that a method might throw.
public class ExceptionThrowingExample {
public static void main(String[] args) {
try {
doWork(5);
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
}
}
public static void doWork(int num) throws Exception {
if (num != 5)
throw new Exception("Invalid value");
else
System.out.println("Work done successfully!");
}
}
Exception Types and Hierarchy
Throwable Class Hierarchy
- Over 60 classes in the hierarchy.
- All types of thrown errors are instances of
Throwableor its subclasses.
List of Checked and Unchecked Exceptions
| Checked Exceptions | Unchecked Exceptions |
|---|---|
| IOException | ArithmeticException |
| SQLException | NullPointerException |
| ClassNotFoundException | ArrayIndexOutOfBoundsException |
| IllegalAccessException | IllegalArgumentException |
| … (and more) | … (and more) |
Handling Exceptions - Best Practices
- Use try-catch blocks for checked exceptions.
- Propagate exceptions if not handled locally.
- Handle runtime exceptions selectively.
Programmer-Defined Exceptions
Example 1
class MyException extends Exception {
private int ex;
MyException(int a) {
ex = a;
}
public String toString() {
return "MyException[" + ex + "] is less than zero";
}
}
class Test {
static void sum(int a, int b) throws MyException {
if (a < 0)
throw new MyException(a);
else
System.out.println(a + b);
}
public static void main(String[] args) {
try {
sum(-10, 10);
} catch (MyException me) {
System.out.println(me);
}
}
}
/* Output:
MyException[-10] is less than zero
*/
Assertions
Sample Use #1
public double deposit(double amount) {
double oldBalance = balance;
balance += amount ;
assert balance > oldBalance;
}
public double withdraw(double amount) {
double oldBalance = balance;
balance -= amount;
assert balance < oldBalance;
}
Sample Use #2
public double deposit(double amount) {
double oldBalance = balance;
balance += amount;
assert balance > oldBalance : "Serious Error – balance did not increase after deposit";
}
Different Uses of Assertions
Precondition Assertions
public class Try {
public static void main(String[] args) {
int gender = 4;
double parkingFee = 10.00;
double tuition = 50.00;
double totalFee;
double roomAndBoard = 0.0;
assert (gender == 1 || gender == 2) : "Invalid";
switch (gender) {
case 1:
totalFee = tuition + parkingFee;
System.out.println(totalFee);
break;
case 2:
totalFee = tuition + roomAndBoard;
System.out.println(totalFee);
break;
}
}
}
Handling Checked Exceptions
When calling a method that can throw checked exceptions:
- Use the try-catch statement and place the call in the try block (i.e., the calling method is catcher), or
- Modify the method header to include the appropriate throws clause (i.e., the calling method is propagator).
Handling Runtime Exceptions
When calling a method that can throw runtime exceptions, it is optional to use the try-catch statement or modify the method header to include a throws clause.
Throwing Exceptions – throw and throws clause
We can write a method that throws an exception directly using the throw reserved word to create a new instance of the Exception or its subclasses. The method header includes the reserved word throws to explicitly specify the exceptions that the method might throw.
public void doWork(int num) throws Exception {
if (num != val)
throw new Exception("Invalid val");
}
Running Programs with Assertions
To run the program with assertions enabled, use java –ea <main class>. If the -ea option is not provided, the program is executed without checking assertions.
How to Enable Assertions in NetBeans
- Right-click on your project name and select Properties.
- Click Run in the left side panel.
- At VM Options, type
-ea.
Assertions (Continued)
Second Form of Assertions
The assert statement may also take the form:
assert <boolean expression>: <expression>;
where <expression> represents the value passed as an argument to the constructor of the AssertionError. The value serves as the detailed message of a thrown exception (customized error message).
Sample Use #2
public double deposit(double amount) {
double oldBalance = balance;
balance += amount;
assert balance > oldBalance : "Serious Error – balance did not increase after deposit";
}
Different Uses of Assertions (Control Flow Invariant)
This statement documents the fact that the default case should never be executed when the program is running correctly.
assert false : "This should never happen";
Exception Types
-
Checked Exceptions: Checked exceptions are checked or detected at compile time. Example:
IOException,SQLException. -
Unchecked Exceptions (Runtime Exceptions): These are detected only at runtime and include programming bugs such as logic errors or improper use of an API. Example:
ArithmeticException,NullPointerException.
Throwable Hierarchy
There are over 60 classes in the Throwable hierarchy.
Programmer-Defined Exceptions
Example 1
class MyException extends Exception {
private int ex;
MyException(int a) {
ex = a;
}
public String toString() {
return "MyException[" + ex + "] is less than zero";
}
}
class Test {
static void sum(int a, int b) throws MyException {
if (a < 0)
throw new MyException(a);
else
System.out.println(a + b);
}
public static void main(String[] args) {
try {
sum(-10, 10);
} catch (MyException me) {
System.out.println(me);
}
}
}
/* Output:
MyException[-10] is less than zero
*/
Assertions
Sample Use #1
public double deposit(double amount) {
double oldBalance = balance;
balance += amount ;
assert balance > oldBalance;
}
public double withdraw(double amount) {
double oldBalance = balance;
balance -= amount;
assert balance < oldBalance;
}
Sample Use #2
public double deposit(double amount) {
double oldBalance = balance;
balance += amount;
assert balance > oldBalance : "Serious Error – balance did not increase after deposit";
}
Different Uses of Assertions
Precondition Assertions
public class Try {
public static void main(String[] args) {
int gender = 4;
double parkingFee = 10.00;
double tuition = 50.00;
double totalFee;
double roomAndBoard = 0.0;
assert (gender == 1 || gender == 2) : "Invalid";
switch (gender) {
case 1:
totalFee = tuition + parkingFee;
System.out.println(totalFee);
break;
case 2:
totalFee = tuition + roomAndBoard;
System.out.println(totalFee);
break;
}
}
}
Handling Checked Exceptions
When calling a method that can throw checked exceptions:
- Use the try-catch statement and place the call in the try block (i.e., the calling method is catcher), or
- Modify the method header to include the appropriate throws clause (i.e., the calling method is propagator).
Handling Runtime Exceptions
When calling a method that can throw runtime exceptions, it is optional to use the try-catch statement or modify the method header to include a throws clause.
Throwing Exceptions – throw and throws clause
We can write a method that throws an exception directly using the throw reserved word to create a new instance of the Exception or its subclasses. The method header includes the reserved word throws to explicitly specify the exceptions that the method might throw.
public void doWork(int num) throws Exception {
if (num != val)
throw new Exception("Invalid val");
}
Running Programs with Assertions
To run the program with assertions enabled, use java –ea <main class>. If the -ea option is not provided, the program is executed without checking assertions.
How to Enable Assertions in NetBeans
- Right-click on your project name and select Properties.
- Click Run in the left side panel.
- At VM Options, type
-ea.
Assertions (Continued)
Second Form of Assertions
The assert statement may also take the form:
assert <boolean expression>: <expression>;
where <expression> represents the value passed as an argument to the constructor of the AssertionError. The value serves as the detailed message of a thrown exception (customized error message).
Sample Use #2
public double deposit(double amount) {
double oldBalance = balance;
balance += amount;
assert balance > oldBalance : "Serious Error – balance did not increase after deposit";
}
Different Uses of Assertions (Control Flow Invariant)
This statement documents the fact that the default case should never be executed when the program is running correctly.
assert false : "This should never happen";
Exception Types
-
Checked Exceptions: Checked exceptions are checked or detected at compile time. Example:
IOException,SQLException. -
Unchecked Exceptions (Runtime Exceptions): These are detected only at runtime and include programming bugs such as logic errors or improper use of an API. Example:
ArithmeticException,NullPointerException.
Throwable Hierarchy
There are over 60 classes in the Throwable hierarchy.
Programmer-Defined Exceptions
Example 1
class MyException extends Exception {
private int ex;
MyException(int a) {
ex = a;
}
public String toString() {
return "MyException[" + ex + "] is less than zero";
}
}
class Test {
static void sum(int a, int b) throws MyException {
if (a < 0)
throw new MyException(a);
else
System.out.println(a + b);
}
public static void main(String[] args) {
try {
sum(-10, 10);
} catch (MyException me) {
System.out.println(me);
}
}
}
/* Output:
MyException[-10] is less than zero
*/
Assertions
Sample Use #1
public double deposit(double amount) {
double oldBalance = balance;
balance += amount ;
assert balance > oldBalance;
}
public double withdraw(double amount) {
double oldBalance = balance;
balance -= amount;
assert balance < oldBalance;
}
Sample Use #2
public double deposit(double amount) {
double oldBalance = balance;
balance += amount;
assert balance > oldBalance : "Serious Error – balance did not increase after deposit";
}
Different Uses of Assertions
Precondition Assertions
public class Try {
public static void main(String[] args) {
int gender = 4;
double parkingFee = 10.
00;
double tuition = 50.00;
double totalFee;
double roomAndBoard = 0.0;
assert (gender == 1 || gender == 2) : "Invalid";
switch (gender) {
case 1:
totalFee = tuition + parkingFee;
System.out.println(totalFee);
break;
case 2:
totalFee = tuition + roomAndBoard;
System.out.println(totalFee);
break;
}
}
}
Handling Checked Exceptions
When calling a method that can throw checked exceptions:
- Use the try-catch statement and place the call in the try block (i.e., the calling method is catcher), or
- Modify the method header to include the appropriate throws clause (i.e., the calling method is propagator).
Handling Runtime Exceptions
When calling a method that can throw runtime exceptions, it is optional to use the try-catch statement or modify the method header to include a throws clause.
Throwing Exceptions – throw and throws clause
We can write a method that throws an exception directly using the throw reserved word to create a new instance of the Exception or its subclasses. The method header includes the reserved word throws to explicitly specify the exceptions that the method might throw.
public void doWork(int num) throws Exception {
if (num != val)
throw new Exception("Invalid val");
}
Running Programs with Assertions
To run the program with assertions enabled, use java –ea <main class>. If the -ea option is not provided, the program is executed without checking assertions.
How to Enable Assertions in NetBeans
- Right-click on your project name and select Properties.
- Click Run in the left side panel.
- At VM Options, type
-ea.