In such a case the runtime suspends execution of your program right at the instruction that committed the violation. If the offending statement is not wrapped inside a try/catch block the compiler will backtrack down the call stack until a try/catch block is found. If no try catch block is found your program will return to the command window and halt with an error message. In a case where no try catch is found for the offending code, your program will not be allowed to execute a single instruction and will return all the back to the command window or whatever environment it was executed from without executing any more of its code.
It is the Java philosophy that no program should continue to execute in a compromised state. Many languages will allow a program to continue running after it has dereferenced a null pointer or indexed an array out of bounds while making no requirement of the program to address that error.
If a method contains a statement capable of throwing a checked Exception, that method must either wrap the statement in a try/catch block or put a throws Exception tag after the method signature.
Sometimes though, it is possible and desirable to recover from an unchecked Exception.
Notice that neither main(), foo1() or foo2() completes. As soon as the exception triggers, control returns from foo2() to foo1(). As soon as control returned to foo1() at the call to foo2(), the runtime saw that foo1() was not handling the Exception either. Control then returned to main() at the call to foo1(). Since main() was not handling the Exception either, control returned to main's caller - the command line, and a stack trace of the offending code's call history is dumped onto the command window.
calling foo1() In foo1() calling foo2() In foo2() You entered int: 1234 Exception in thread "main" java.lang.NumberFormatException: For input string: "fubar" at java.lang.NumberFormatException.forInputString(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at ExceptionsDemo1.foo2(ExceptionsDemo1.java:44) at ExceptionsDemo1.foo1(ExceptionsDemo1.java:25) at ExceptionsDemo1.main(ExceptionsDemo1.java:16) |
If we were to remove the throws IOException from the above program and recompile it, the compiler will give the following errors.
C:\Users\tim\Desktop\ExceptionHandling>javac ExceptionsDemo2.java ExceptionsDemo2.java:26: error: unreported exception FileNotFoundException; must be caught or declared to be thrown Scanner infile = new Scanner (f ); ^ 1 error C:\Users\tim\Desktop\ExceptionHandling> |
You probably noticed that the catch block looks similar to a method definition. When a statement inside the try block triggers an Exception, control jumps into the try block just as if the catch block was a method - and it brings into the catch block an Exception object containing info about what happened.
This mechanism might remind you of event programing when you clicked a JButton the runtime automatically called your actionPerformed method and passed in an event object containing info about the event that triggered the jump into the method.
The major difference in behavior with an Exception is that we don't return back from the catch block. Instead we execute the catch block and then drop past the end of the catch block and resume execution after it.
Often there are multiple statements in a try block that could throw different types of Exceptions. We could use a shotgun approach and just have one single catch block looking for Exception (the general case) that will catch any Exception (and any sub type of Exception) that occurs. Usually we want to know which specific type of Exception occurred and handle it distinctly. To do that we stack multiple catch blocks under the single try block. Always put the more specific sub type first and the most general at the bottom. Each block is written such that it will only get triggered for the specific Exception type in the catch definition.
Once we have a separate catch block under the try block for each kind of Exception our try code might produce, we can now put a general Exception catch bloc at the very bottom as a catch all in case an unplanned/unexpected Exception occurs. It's similar to a long chained if else . . . if else statement with an unqualified else at the bottom. If none of the if tests match then the else at the bottom is the catch all case that executes. Like a chained if else, our catch blocks are stacked and we only execute at most one of them if an exception triggers, and that will be the first case that matches. This is why we must put the specific Exception subtypes at the top and save the general catch all Exception for the bottom.
If there is a finally block at the bottom - that finally block IS executed. Understand that even if the code in the try block executes cleanly with no exception - the finally block STILL executes. Always keep that in mind that if you write a finally block at the bottom underneath your catch block()s, it will execute regardless of whether an exception is triggered or not.
calling foo1() 1st line of infile was: Hello World Caught NumberFormatException: java.lang.NumberFormatException: For input string: "Hello World" returning from main() |
Sometimes it is convenient to manually throw an exception yourself because you want to treat a case that does not put your program into an undefined state (i.e. its not an error) as if it is an error and handle it with a catch block just a like a an exception thrown by the runtime.
manner as real exceptions