Customized Exceptions
Sometimes during creating a program, there is a requirement of some special exception which is not available. So in such situation Java gives us the facility to create our own exceptions called as customized exceptions. Consider the following example of a customized_exception,
import java.util.Scanner; class TooYoungException extends RuntimeException { TooYoungException(String str) { super(str); } } class TooOldException extends RuntimeException { TooOldException(String str) { super(str); } } public class ExampleOne { public static void main(String []args) { Scanner s = new Scanner(System.in); System.out.println("Enter your current age: "); int age = s.nextInt(); if(age > 60) { throw new TooOldException("You are too old to get married."); } else if(age < 18) { throw new TooYoungException("You are too young to get married."); } else { System.out.println("You will get the details of the match by the email."); } } }
Output of the above code will be:
Enter your current age: 25 You will get the details of the match by the email.
Note- A good practice is to keep our customized_exception class uncheck i.e. we have to extend RuntimeException class rather than Exception class while defining our customized_exceptions.
Possible Compile Time Error in Exception Handling
There are various conditions in which the program can give compile time error, some of these errors are:
- Exception xxx has already been caught.
- Unreported exception xxx must be caught or declared to be thrown.
- Exception xxx never throws in the body of corresponding try statement.
- Try without catch or finally.
- Finally without try.
- Catch without try.
- Unreachable statement.
- Incompatible types
Try with resources
While using try block there is a use of multiple resources in the program. Sometimes these resources needes to be free or close in order to use them correctly, but there can be a case when a programmer forgets to close them in finally block. Therefore in order to use the resources judiciously, we use enhanced_try_block. In this try block, the define resources are having local scope and they will close automatically as soon as the block ends. These resources are by default declare as final variable.
Consider the following example in which a database connection has the case of open and close in finally block.
Connection conn = null; try { Class.forName("oracle.jdbc.OracleDriver"); System.out.println("Driver successfully loaded"); conn=DriverManager.getConnection("jdbc:oracle:thin:@//System/xe","tiger","scott"); System.out.println("Connection Established."); } catch(Exception ex) { System.out.println("Exception In Opening Connection In DBConnection:"+ex); ex.printStackTrace(); } finally { try { conn.close(); System.out.println("Connection Closed."); } catch(Exception ex){ System.out.println("Exception In Closing Connection In DBConnection:"+ex); } }
Better version of the above code using try with resources will be as follows:
String str = "jdbc:oracle:thin:@//System/xe"; String name = "tiger"; String password = "scott"; try(Connection conn = DriverManager.getConnection(str,name,password)) //resource { System.out.println("Connection Established with Database."); //code } catch(Exception ex) { System.out.println("Error in establishing connection with database."); ex.printStackTrace(); }
Note- There can be multiple resources declarations between the parenthesis but they should be separate, with a semicolon. Consider the following example in which there are multiple resources.
try(FileWriter fw = new FileWriter("First.txt"); FileReader fr = new FileReader("Second.txt")) { //code } catch(Exception ex) { //handling code }
Note- The declaration of resources with try should be the one which can automatically close themselves i.e. they should implement java.lang.AutoClosable interface. Some of the resources which implements this interface are database resources, file handling resources, networking resources and many more.
Multi Catch Block
If we define a try block with multiple catch block such that we define more than 1 catch block with almost same handling code then in such case 2 or more try blocks can merge in a particular way. It improves the readability of the code and reduces its size. For example,
try { //code } catch(IllegalStateException ex) //1st catch block { ex.printStackTrace(); } catch(NullPointerException ex) //2nd catch block { ex.printStackTrace(); } catch(AssertException ex) //3rd catch block { ex.getMessage(); } catch(InterruptedException ex) //4th catch block { ex.getMessage(); }
As in the above code it can be seen that 1st and 2nd catch block’s body is similar and 3rd and 4th catch block’s body are also similar. In such case multiple catch blocks can be used. So the upgraded version of the above code will be as
try { //code } catch(IllegalStateException | NullPointerException ex) //1st and 2nd catch block { ex.printStackTrace(); } catch(AssertException | InterruptedException ex) //3rd and 4th catch block { ex.getMessage(); }
Note- One thing should be kept in mind while using the multiple catch block, i.e. in single catch block both child class and parent class should not be defined as it can lead to compile time error.