Exception Rules in Java
-
Last Updated: November 4, 2024
-
By: javahandson
-
Series
Understand the key exception rules in Java including how checked and unchecked exceptions are handled. Also, the impact of inheritance and polymorphism on exception handling and compliance with method overloading and overriding rules.
Overloading means defining multiple methods with the same name but different parameters.
Every overloaded method can declare its own set of checked or unchecked exceptions without affecting the others. As overloaded methods are independent of each other they can throw different exceptions. The caller has to handle only the exception of the specific overloaded method. Hence we don’t have to be concerned about exception rules for overloaded methods.
Write a program to test the exception rules for overloaded methods ( Checked exception )
In the below example, we will create an #addition method that adds 2 numbers and throws an IOException i.e. a checked exception. We will overload this #addition method to add 3 numbers and throw an IllegalAccessException i.e. also a checked exception.
As the addition methods are overloaded hence no rules are applied and no compilation issue will be thrown.
package com.javahandson; import java.io.IOException; public class ExceptionRules { public int addition(int a, int b) throws IOException { return a + b; } public int addition(int a, int b, int c) throws IllegalAccessException { return a + b + c; } public static void main(String[] args) throws IOException, IllegalAccessException { ExceptionRules exceptionRules = new ExceptionRules(); System.out.println("Addition of 2 numbers : "+exceptionRules.addition(5, 10)); System.out.println("Addition of 3 numbers : "+exceptionRules.addition(5, 10, 15)); } } Output: Addition of 2 numbers : 15 Addition of 3 numbers : 30
Write a program to test the exception rules for overloaded methods ( UnChecked exception )
We will continue using the above example but here will throw unchecked exceptions instead of checked exceptions. As we know the addition methods are overloaded methods hence no rules are applied and no compilation issue will be thrown.
package com.javahandson; public class ExceptionRules { public int addition(int a, int b) throws ArithmeticException { return a + b; } public int addition(int a, int b, int c) throws NumberFormatException { return a + b + c; } public static void main(String[] args) { ExceptionRules exceptionRules = new ExceptionRules(); System.out.println("Addition of 2 numbers : "+exceptionRules.addition(5, 10)); System.out.println("Addition of 3 numbers : "+exceptionRules.addition(5, 10, 15)); } } Output: Addition of 2 numbers : 15 Addition of 3 numbers : 30
We will also check if there is any impact when one method throws a checked exception and the other overloaded method throws an unchecked exception.
package com.javahandson; import java.io.IOException; public class ExceptionRules { public int addition(int a, int b) throws IOException { return a + b; } public int addition(int a, int b, int c) throws ArithmeticException { return a + b + c; } public static void main(String[] args) throws IOException { ExceptionRules exceptionRules = new ExceptionRules(); System.out.println("Addition of 2 numbers : "+exceptionRules.addition(5, 10)); System.out.println("Addition of 3 numbers : "+exceptionRules.addition(5, 10, 15)); } } Output: Addition of 2 numbers : 15 Addition of 3 numbers : 30
So the above program also worked properly without any issues.
All the above examples confirm that there are no exception rules for overloaded methods hence we don’t have to think much about exception rules when it comes to overloading.
Overriding means redefining a method in a subclass that exists in the parent class ensuring the subclass provides a specific implementation. Exception Rules are applicable for overridden methods. In this context, exception handling follows the below rules.
An overridden method in a subclass cannot throw new or broader checked exceptions than those declared in the superclass method. The subclass method can throw lesser or more specific exceptions i.e. a subtype of the exception declared in the superclass. But if a broader exception is thrown then we will get a compilation issue.
In the below example, we will create an #area method in the parent class that calculates the area of a rectangle and throws an IOException i.e. a checked exception. We will override this #area method in the subclass to calculate the area of a triangle and throw a narrow checked exception i.e. FileNotFoundException.
package com.javahandson; import java.io.FileNotFoundException; import java.io.IOException; class Parent { public int area(int a, int b) throws IOException { return a * b; } } class Child extends Parent { public int area(int a, int b) throws FileNotFoundException { return (a * b)/2; } } public class ExceptionRules { public static void main(String[] args) throws IOException { Parent parent = new Parent(); System.out.println("area of rectangle : "+parent.area(10, 20)); Parent child = new Child(); System.out.println("area of triangle : "+child.area(10, 20)); } } Output: area of rectangle : 200 area of triangle : 100
In the above example as the subclass throws a narrow exception, the rules are met and the program runs successfully.
Now we will test a scenario when we throw a broader checked exception from the overridden method. We will continue using the same example as above but this time we will throw a broader checked exception in the subclass.
package com.javahandson; import java.io.IOException; class Parent { public int area(int a, int b) throws IOException { return a * b; } } class Child extends Parent { public int area(int a, int b) throws Exception { // Here we encounter an compilation issue as overridden method has broaden the exception of the super class method. return (a * b)/2; } } public class ExceptionRules { public static void main(String[] args) throws IOException { Parent parent = new Parent(); System.out.println("area of rectangle : "+parent.area(10, 20)); Parent child = new Child(); System.out.println("area of triangle : "+child.area(10, 20)); } } Output: Exception in thread "main" java.lang.Error: Unresolved compilation problem: Exception Exception is not compatible with throws clause in Parent.area(int, int) at com.javahandson.Child.area(ExceptionRules.java) at com.javahandson.ExceptionRules.main(ExceptionRules.java)
In the above example as the subclass is throwing a broader exception, the rules are not met and the program is not compiled.
From the above, we learned that for checked exceptions we have to throw the same or narrow exception in overridden methods but there is one more catch it is not necessary to throw an exception in the subclass method even if the superclass method throws a checked exception.
package com.javahandson; import java.io.FileNotFoundException; import java.io.IOException; class Parent { public int area(int a, int b) throws IOException { return a * b; } } class Child extends Parent { public int area(int a, int b) { return (a * b)/2; } } public class ExceptionRules { public static void main(String[] args) throws IOException { Parent parent = new Parent(); System.out.println("area of rectangle : "+parent.area(10, 20)); Parent child = new Child(); System.out.println("area of triangle : "+child.area(10, 20)); } } Output: area of rectangle : 200 area of triangle : 100
There are no restrictions on throwing unchecked exceptions, as they are not part of the method signature.
In the below example, we will throw a broader unchecked exception and as there are no restrictions for throwing unchecked exceptions hence the program will run successfully.
package com.javahandson; import java.io.IOException; class Parent { public int area(int a, int b) throws ArithmeticException { return a * b; } } class Child extends Parent { public int area(int a, int b) throws RuntimeException { return (a * b)/2; } } public class ExceptionRules { public static void main(String[] args) throws IOException { Parent parent = new Parent(); System.out.println("area of rectangle : "+parent.area(10, 20)); Parent child = new Child(); System.out.println("area of triangle : "+child.area(10, 20)); } } Output: area of rectangle : 200 area of triangle : 100
In the below example, we will throw a narrow unchecked exception and as expected the program will run properly.
package com.javahandson; class Parent { public int getValue() throws IndexOutOfBoundsException { int[] numbers = {1, 2, 3}; return numbers[2]; } } class Child extends Parent { public int getValue() throws StringIndexOutOfBoundsException { String str = "Hello"; return str.charAt(4); } } public class ExceptionRules { public static void main(String[] args) { Parent parent = new Parent(); System.out.println("Fetch the value from an array : "+parent.getValue()); Parent child = new Child(); System.out.println("Fetch the value from an string : "+ (char)child.getValue()); } } Output: Fetch the value from an array : 3 Fetch the value from an string : o
So this is all about exception rules in Java. If you have any questions on this topic, please raise them in the comments section. If you liked this article then please share this post with your friends and colleagues.