Java Exception
Exception mechanism helps developers find issues of their programs. Its base class is java.lang.Throwable which consists of java.lang.Error and java.lang.Exception. In this post, I will talk about five keywords about Java exception, how to catch multiple exceptions and demonstrate how to define our own exception class.
Types of Throwable Derived Class
- Exception: Issues when compiling the Java code
- RuntimeException: Issues when running the Java code
- Error: Source code must be modified to fix the error
Two Approaches to Handle Exception
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse("1999-0909");
System.out.println(date);
}
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse("1999-0909");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date);
}
KeyWord 1: throw
We can use ’throw’ keyword to throw a specific exception from a specific method.
- ’throw’ must be put inside of the method
- ’throw’ must be followed by ’new’ keyword and an exception object or its derived object
- For exceptions:
- If it is a RuntimeException or its derived object, JVM will handle it (print and pause).
- If it is a compiling exception, we need to handle it (throws or try catch).
public static int getElement(int[] arr, int index) {
// if arr is null, throw exception
if (arr == null) throw new NullPointerException("arr[] is null");
// if index is invalid
if (index < 0 || index >= arr.length) throw new ArrayIndexOutOfBoundsException("Index is invalid");
int ele = arr[index];
return ele;
}
KeyWord 2: throws
We can use ’throws’ keyword to ask the invoking method to handle the exception.
- ’throws’ keyword must be put at the line of the function declaration
- ’throws’ must be followed by exceptions (can only put the derived exception)
// We can only specify 'Exception'
// Because FileNotFoundException extends IOException extends Exception
public static void readFile(String fileName) throws FileNotFoundException, IOException {
if (!fileName.endsWith(".txt")) {
throw new IOException("File format is wrong!");
}
if (!fileName.equals("c:\\a.txt")) {
throw new FileNotFoundException("File path is wrong!");
}
}
// Let JVM to handle the exception
public static void main(String[] args) throws FileNotFoundException, IOException {
readFile("c:\\a.txt");
System.out.println("Read File");
}
KeyWord 3, 4: try … catch
We can use try … catch to handle exceptions without pausing the following program.
- ’try’ may throw multiple exceptions, therefore, we can use multiple ‘catch’ to handle these exceptions.
public static void readFile(String fileName) throws IOException{
if (!fileName.endsWith(".txt")) {
throw new IOException("File format is wrong!");
}
System.out.println("File format is correct!");
}
// Let JVM to handle the exception
public static void main(String[] args) {
try {
readFile("c:\\a.pdf");
} catch (IOException e) {
// Throwable has 3 methods to handle exceptions
System.out.println(e.getMessage()); // File format is wrong!
System.out.println(e.toString()); // java.io.IOException: File format is wrong!
e.printStackTrace();
// java.io.IOException: File format is wrong!
// at Demo01TryCatch.readFile(Demo01TryCatch.java:7)
// at Demo01TryCatch.main(Demo01TryCatch.java:15)
}
System.out.println("Following code");
}
KeyWord 5: finally
We can use ‘finally’ keyword to force the execution of some code blocks no matter if there are exceptions or not.
If readFile() function throws an exception, then the following printing function will not be executed.
public static void main(String[] args) {
try {
readFile("c:\\a.txt");
System.out.println("If the program is wrong, this sentence will not be printed!");
} catch (IOException e) {
System.out.println(e.getMessage());
}
System.out.println("Following code");
}
To force the printing function to execute, we can use ‘finally’ keyword.
‘finally’ keyword is normally used to recycle resources.
public static void main(String[] args) {
try {
readFile("c:\\a.txt");
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
System.out.println("This sentence will be printed anyway!");
}
System.out.println("Following code");
}
Handle Multiple Exceptions
Approach 1: Try and catch exceptions separately
public static void main(String[] args) {
int[] arr = {1, 2, 3};
List<Integer> list = List.of(1, 2, 3);
try {
System.out.println(arr[3]); // java.lang.ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
}
try {
System.out.println(list.get(3)); // java.lang.ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
}
System.out.println("Following Code");
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// Following Code
}
Approach 2: Try once and catch exceptions one by one
public static void main(String[] args) {
int[] arr = {1, 2, 3};
try {
System.out.println(arr[3]); // java.lang.ArrayIndexOutOfBoundsException
System.out.println(15 / 0); // java.lang.ArithmeticException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
} catch (ArithmeticException e) {
System.out.println(e);
}
System.out.println("Following Code");
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// Following Code
}
- Derived exception must be caught first.
- Because of polymorphism, derived exception object can be accepted by the base exception class. Therefore, derived exception class defined in the next catch branch will not be invoked.
Exceptions in inheritance
- When derived class overrides the method of the base class:
- The overridden method can throw the same exceptions.
- The overridden method can throw derived exceptions.
- The overridden method can throw no exceptions.
- The overridden method can not throw exceptions, if the base class method does not throw any exceptions.
- The overridden method can use try catch to handle exceptions generated.
public class BaseClass {
public void show01() throws NullPointerException, ClassCastException{}
public void show02() throws IndexOutOfBoundsException{}
public void show03() throws IndexOutOfBoundsException{}
public void show04() {}
}
class DerivedClass extends BaseClass {
@Override
public void show01() throws NullPointerException, ClassCastException {
super.show01();
}
@Override
public void show02() throws ArrayIndexOutOfBoundsException {
super.show02();
}
@Override
public void show03() {
super.show03();
}
@Override
public void show04() {
super.show04();
}
}
User-defined Exceptions
Define the exception class
public class RegisterException extends Exception {
public RegisterException() {
}
public RegisterException(String message) {
super(message);
}
}
Demo
public class DemoRegisterException {
static String[] userNames = {"Jason", "Kevin", "Joey"};
public static void main(String[] args) throws RegisterException {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter the user name that you want to register: ");
String userName = sc.next();
check(userName);
}
public static void check(String userName) throws RegisterException {
for (String name : userNames) {
if (name.equals(userName)) {
throw new RegisterException("This user name has been occupied!");
}
}
System.out.println("Success in registering this user name!");
}
}