Você está na página 1de 61

Handling Exceptions

Error detection and handling may be the most important ingredient of any application. Java arms developers with an elegant mechanism for handling errors that produces efficient and organized error-handling code: exception handling.

Handling Exceptions
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions. When an error occurs within a method, the method creates an object and hands it off to the runtime system.

Handling Exceptions
The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.

Handling Exceptions
After a method throws an exception, the runtime system attempts to find something to handle it. The set of possible "somethings" to handle the exception is the ordered list of methods that had been called to get to the method where the error occurred. The list of methods is known as the call stack

Exception Hierarchy

Handling Exceptions
The runtime system searches the call stack for a method that contains a block of code that can handle the exception. This block of code is called an exception handler. The search begins with the method in which the error occurred and proceeds through the call stack in the reverse order in which the methods were called.

Handling Exceptions
When an appropriate handler is found, the runtime system passes the exception to the handler. An exception handler is considered appropriate if the type of the exception object thrown matches the type that can be handled by the handler.

Handling Exceptions
The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches all the methods on the call stack without finding an appropriate exception handler, as shown in the next figure, the runtime system (and, consequently, the program) terminates.

Handling Exceptions
The code that might throw certain exceptions must be enclosed by either of the following: 1.) A try statement that catches the exception. The try must provide a handler for the exception, as described in Catching and Handling Exceptions. 2.) A method that specifies that it can throw the exception. The method must provide a throws clause that lists the exception, as described in Specifying the Exceptions Thrown by a Method.

Handling Exceptions
1.) checked exception 2.) error 3.) runtime exception

Checked Exceptions
ClassNotFoundException InterruptedException SQLException IOException FileNotFoundException

Unchecked Exceptions
Unchecked Exceptions are the sub classes of RuntimeException class RuntimeException NullPointerException ArithmeticException ArrayIndexOutOfBoundsException ClassCastException

Catching and Handling Exceptions


The first step in constructing an exception handler is to enclose the code that might throw an exception within a try block. In general, a try block looks like the following. try { code } catch and finally blocks . . .

Catching and Handling Exceptions


If an exception occurs within the try block, that exception is handled by an exception handler associated with it. To associate an exception handler with a try block, you must put a catch block after it

Catching and Handling Exceptions


try { // risky code } catch (ExceptionType1 name) { } catch (ExceptionType2 name) { } finally{ } The ExceptionType must be the name of a class that inherits from the Throwable class

Catching and Handling Exceptions


The catch block contains code that is executed if and when the exception handler is invoked. If an exception is not thrown in the try block, the code in the catch clause will not execute. class Test{ public static void main(String[] args){ int x = 10; try{ System.out.println(x / 0); }catch(ArithmeticException e){ System.out.println(Caught); } } }

Catching and Handling Exceptions


class DemoException{ public static void main(String[] args){ int x = 10; System.out.println(x/0); } } For the integer data type division by zero is not defined, hence will cause an exceptional situation at runtime. This will generate a java.lang.ArithmeticException

Catching and Handling Exceptions


To handle the above exception we can surround the code with a try block with an appropriate catch clause like the following.
int x = 10;

try{
System.out.println(x/0);

}catch(ArithmeticException ae){ ae.printStackTrace(); }

The finally Block


The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. The runtime system always executes the statements within the finally block regardless of what happens within the try block.

The finally Block


The finally block is executed regardless of what happens within the try block.
class Test{ public static void main(String[] args){ int x = 10; try{ System.out.println(x / 0); }catch(ArithmeticException e){ System.out.println(Caught); }finally{ System.out.println(Finally); } } }

Output :

Caught Finally

The finally Block


class Test{ public static void main(String[] args){ // the try block doesnt give any exceptions try{ System.out.println(No exceptions); }catch(ArithmeticException e){ System.out.println(Caught); }finally{ System.out.println(Finally); } } }

Output : NoExceptions Finally

Syntaxes of try block


The following legal code demonstrates a try with a finally but no catch: try {
// We can only have unchecked exceptions here

} finally { //clean up }

Syntaxes of try block


The following legal code demonstrates a try, catch, and finally:

try { // do stuff } catch (SomeException ex) { // do exception handling } finally { // clean up }

Syntaxes of try block


The following ILLEGAL code demonstrates a try without a catch or finally:

try { // do stuff } // need a catch or finally here System.out.println("out of try block");

Syntaxes of try block


The following ILLEGAL code demonstrates a misplaced catch block:

try { // do stuff } // can't have code between try/catch System.out.println("out of try block"); catch(Exception ex) { }

Important Facts
It is illegal to use a try clause without either a catch clause or a finally clause. A try clause by itself will result in a compiler error. Any catch clauses must immediately follow the try block. Any finally clause must immediately follow the last catch clause (or it must immediately follow the try block if there is no catch). It is legal to omit either the catch clause or the finally clause, but not both.

How to Throw Exceptions


Before you can catch an exception, some code somewhere must throw one. Any code can throw an exception: your code, code from a package written by someone else such as the packages that come with the Java platform, or the Java runtime environment. Regardless of what throws the exception, it's always thrown with the throw statement.

The throw Statement


All methods use the throw statement to throw an exception. The throw statement requires a single argument: a throwable object. Throwable objects are instances of any subclass of the Throwable class. Here's an example of a throw statement. throw someThrowableObject;

Let's look at the throw statement in context. The following pop method is taken from a class that implements a common stack object. The method removes the top element from the stack and returns the object.

The throw Statement


The pop method checks to see whether any elements are on the stack. If the stack is empty (its size is equal to 0), pop instantiates a new EmptyStackException object (a member of java.util) and throws it. You MUST remember that you can throw only objects that inherit from the java.lang.Throwable class.

The throw Statement


After the throw statement you will not be able to have any other statements. The compiler will give you an error. class A{ void m(){ System.out.println("Before"); throw new ArithmeticException();// compile error System.out.println("After"); // unreachable statement } }

The throw Statement


import java.io.*; class A{ void m() throws Exception{ System.out.println("Before"); throw new IOException();// compile error System.out.println("After"); // unreachable statement } }

Uncaught Exceptions
class TestEx { public static void main (String [] args) { doStuff(); // calling the method in main (1) } static void doStuff() { doMoreStuff(); // calling another method } static void doMoreStuff() { int x = 5/0; // Can't divide by zero! // ArithmeticException is thrown here } }

Cont.. Uncaught Exceptions


The above code will result in an exception at runtime. Exception in thread "main" java.lang.ArithmeticException: / by zero at TestEx.doMoreStuff(TestEx.java:10) at TestEx.doStuff(TestEx.java:7) at TestEx.main(TestEx.java:3)

Uncaught exceptions
To avoid the above exception we could do 3 things. 1.) static void doMoreStuff() { try{ int x = 5/0; }catch(Exception e ){
System.out.println(Caught);

} }

2.) static void doStuff() { try{ doMoreStuff(); }catch(Exception e ){


System.out.println(Caught);

} }

public static void main (String [] args) {

try{ doStuff(); }catch(Exception e ){


System.out.println(Caught);

}
}

Guarded Methods
If we throw a checked exception from a method the compiler will not allow the code to be compiled. Eg : void m (){ throw new IOException(); // This code does not compile }

Guarded Methods
To make the above code compile we have to do any of the following 2 things. 1.) surround the throw statement in a try catch (HANDLING) 2.) add a throws clause to the main method (DECLARING)

Guarded Methods
1.) HANDLING the exception void m (){ try{ throw new IOException(); }catch(Exception e ){ System.out.println(caught) ; }

Guarded Methods
2.) DECLARING the exception void m () throws Exception{ throw new IOException(); }

The throws clause


With the throws clause we can have checked and unchecked exceptions If we call a guarded method with a checked exception , then again we have to handle or declare the exception in the calling method.

The throws clause

The throws clause

The throws clause

Extending class Exception


We can extend the class Exception and create our own exception Eg : class MyException extends Exception Then that class will be treated as a compile time checked exception

Extending class Exception


class MyException extends Exception {} class TestException { public static void main(String[] args ){ TestException te = new TestException () ; te.m() ; } void m() throws MyException{ System.out.println("Guarded method"); } }

Extending class Exception


class MyException extends Exception {} class TestException { public static void main(String[] args ){ TestException te = new TestException () ; try{ te.m() ; // Handling the exception }catch(Exception e){ System.out.println("Caught"); } } void m() throws MyException{ System.out.println("Guarded method"); // No actual
exception

} Output Guarded method

Extending class Exception


class MyException extends Exception {} class TestException { public static void main(String[] args ) throws MyException{ // Declaring the Exception TestException te = new TestException () ; te.m() ; } void m() throws MyException{ System.out.println("Guarded method"); } } Output Guarded method

Overriding Methods
With respect to the method it overrides, the overriding method The overriding method CAN throw any unchecked (runtime) exception, regardless of whether the overridden method declares the exception. The overriding method must NOT throw checked exceptions that are new or broader than those declared by the overridden method.

Overriding Methods
For example, a method that declares a FileNotFoundException cannot be overridden by a method that declares a SQLException, Exception, or any other non-runtime exception unless it's a subclass of FileNotFoundException.
The overriding method can throw narrower or fewer exceptions. Just because an overridden method "takes risks" doesn't mean that the overriding subclass exception takes the same risks.

Overriding Methods
Bottom line: an overriding method doesn't have to declare any exceptions that it will never throw, regardless of what the overridden method declares.

Overriding Methods
If a method is overridden but you use a polymorphic (supertype) reference to refer to the subtype object with the overriding method, the compiler assumes youre calling the supertype version of the method. If the supertype version declares a checked exception, but the overriding subtype method does not, the compiler still thinks you are calling a method that declares an exception (more in Chapter 5). Lets take a look at an example:

class Animal { public void eat() throws Exception { // throws an Exception } } class Dog2 extends Animal { public void eat() { // no Exceptions } public static void main(String [] args) { Animal a = new Dog2(); Dog2 d = new Dog2(); d.eat(); // ok a.eat(); // compiler error // unreported exception } } This code will not compile because of the Exception declared on the Animal eat() method. This happens even though, at runtime, the eat() method used would be the Dog version, which does not declare the exception.

Examples of Legal and Illegal Method Overrides


public class Animal { public void eat() { } }

Overloading Methods
Overloaded methods MUST change the argument list. Overloaded methods CAN change the return type. Overloaded methods CAN change the access modifier. Overloaded methods CAN declare new or broader checked exceptions.

Overloading Methods
A method can be overloaded in the same class or in a subclass. In other words, if class A defines a doStuff(int i) method, the subclass B could define a doStuff(String s) method without overriding the superclass version that takes an int. So two methods with the same name but in different classes can still be considered overloaded, if the subclass inherits one version of the method and then declares another overloaded version in its class definition.

Overloading Methods
Be careful to recognize when a method is overloaded rather than overridden. You might see a method that appears to be violating a rule for overriding, but that is actually a legal overload, as follows:

public class Foo { public void doStuff(int y, String s) { } public void moreThings(int x) { } } class Bar extends Foo { public void doStuff(int y, long s) throws IOException { } }

Legal Overloads
Let's look at a method we want to overload: public void changeSize(int size, String name, float pattern) { } The following methods are legal overloads of the changeSize() method: public void changeSize(int size, String name) { } public int changeSize(int size, float pattern) { } public void changeSize(float pattern, String name) throws IOException { }

Você também pode gostar