Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 14. Διαχείριση σφαλμάτων (Exception Handling) Χειμερινό Εξάμηνο 2012 Πέτρος Κωμοδρόμος [email protected] http://www.eng.ucy.ac.cy/petros ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 1 Θέματα Εισαγωγή στη διαχείριση σφαλμάτων Παράδειγμα: ArithmeticExceptions και InputMismatchExceptions χωρίς και με διαχείριση εξαιρέσεων (exception handling) Χρήση του μηχανισμού διαχείρισης εξαιρέσεων (exception handling) Ιεραρχία διαχείρισης εξαιρέσεων (exception handling) try, throw και catch finally block Stack Unwinding Μέθοδοι printStackTrace, getStackTrace και getMessage Chained Exceptions Ορισμός νέων τύπων Exceptions ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 2 Εισαγωγή Εξαίρεση (Exception): μία ένδειξη ότι κάτι συμβαίνει λάθος κατά την εκτέλεση ενός προγράμματος. Exception handling – μηχανισμός διαχείρισης εξαιρέσεων (exceptions) που μπορεί να συμβούν κατά τη διάρκεια της εκτέλεσης ενός προγράμματος ώστε να μπορέσει να συνεχίσει ή τουλάχιστο να τερματίσει την εκτέλεση με ελεγχόμενο τρόπο. Με τους μηχανισμούς διαχείρισης εξαιρέσεων (exception handling) μπορούν να φτιαχτούν πιο ανεκτικά σε σφάλματα και αξιόπιστα προγράμματα (more robust and fault-tolerant programs). Η εξαίρεση (exception) περιέχει πληροφορίες για το τι έχει συμβεί. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 3 Όταν ένα αναπάντεχο συμβάν προκύψει κατά την εκτέλεση ενός προγράμματος Java, το πρόγραμμα ρίχνει (throws) μία εξαίρεση (exception) και το σύστημα προσπαθεί να βρει κατάλληλο διαχειριστή εξαιρέσεων για να το διαχειριστεί. Ένας διαχειριστής εξαιρέσεων (exception handler) μπορεί να πιάσει (catch) δηλαδή να αναλάβει να διαχειριστεί κάποιο exception βάσει του τύπου του exception και του τύπου που ορίζεται στη δήλωση του catch. Αν δεν βρει κάποιο κατάλληλο διαχειριστή εξαιρέσεων (exception handler) για να το διαχειριστεί χρησιμοποιείται ο default exception handler, ο οποίος εκτυπώνει κάποιες πληροφορίες και ακολούθως τερματίζεται η εκτέλεση του προγράμματος. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 4 The Throwable class ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 5 Στην Java μία εξαίρεση (exception) είναι αντικείμενο της τάξης Throwable ή κάποιας υποτάξης της. Όλα τα exceptions τα οποία πρέπει να διαχειριστεί κάποιος είναι τα checked exceptions δηλαδή αντικείμενα κάποιας υποτάξης της Exception και όχι της Error, αλλά ούτε και υποτάξεων της RuntimeException. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 6 Παραδείγματα Εξαιρέσεων ArrayIndexOutOfBoundsException: προσπάθεια για πρόσβαση στοιχείου πέρα από τα όρια ενός πίνακα: ClassCastException: προσπάθεια να γίνει cast ένα αντικείμενο το όποίο δεν έχει σχέση is-a με τον τύπο που χρησιμοποιείται στον τελεστή του cast : ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 7 NullPointerException: όταν μία null αναφορά χρησιμοποιείται όπου αναμένεται ένα αντικείμενο: FileNotFoundException: όταν μια προσπάθεια να ανοιχθεί ένα αρχείο με συγκεκριμένο όνομα (specified pathname) αποτύχει: ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 8 Χαρακτηριστικά Εξαιρέσεων Thrown exception: μία εξαίρεση (exception) που έχει συμβεί Stack trace: • Όνομα της εξαίρεση (exception) σε ένα μήνυμα που περιγράφει το πρόβλημα • Ολοκληρωμένη method-call stack ArithmeticException: μπορεί να προκύψει από μία σειρά από διαφορετικά προβλήματα αριθμητικού χαρακτήρα Throw point : το αρχικό σημείο όπου η εξαίρεση συνέβηκε (top row of call chain) InputMismatchException: συμβαίνει όταν η μέθοδος nextInt του Scanner λαμβάνει ένα string το οποίο δεν αντιπροσωπεύει ένα έγκυρο ακέραιο ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 9 1 // Fig. 13.1: DivideByZeroNoExceptionHandling.java 2 // An application that attempts to divide by zero. 3 import java.util.Scanner; 4 5 public class DivideByZeroNoExceptionHandling 6 7 { // demonstrates throwing an exception when a divide-by-zero occurs 8 9 public static int quotient( int numerator, int denominator ) { 10 11 return numerator / denominator; // possible division by zero } // end method quotient 12 13 14 15 16 public static void main( String args[] ) { Scanner scanner = new Scanner( System.in ); // scanner for input 17 System.out.print( "Please enter an integer numerator: " ); 18 19 20 int numerator = scanner.nextInt(); System.out.print( "Please enter an integer denominator: " ); int denominator = scanner.nextInt(); 21 22 23 24 int result = quotient( numerator, denominator ); System.out.printf( Attempt to divide; denominator may be zero Read input; exception occurs if input is not a valid integer "\nResult: %d / %d = %d\n", numerator, denominator, result ); 25 } // end main 26 } // end class DivideByZeroNoExceptionHandling Please enter an integer numerator: 100 Please enter an integer denominator: 7 Result: 100 / 7 = 14 ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 10 Outline Please enter an integer numerator: 100 Please enter an integer denominator: 7 Result: 100 / 7 = 14 Please enter an integer numerator: 100 Please enter an integer denominator: 0 Exception in thread "main" java.lang.ArithmeticException: / by zero at DivideByZeroNoExceptionHandling.quotient(DivideByZeroNoExceptionHandling.java:10) at DivideByZeroNoExceptionHandling.main(DivideByZeroNoExceptionHandling.java:22) Please enter an integer numerator: 100 Please enter an integer denominator: hello Exception in thread "main" java.util.InputMismatchException at java.util.Scanner.throwFor(Unknown Source) at java.util.Scanner.next(Unknown Source) at java.util.Scanner.nextInt(Unknown Source) at java.util.Scanner.nextInt(Unknown Source) at DivideByZeroNoExceptionHandling.main(DivideByZeroNoExceptionHandling.java:20) ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 11 Catching Exceptions catch block – λαμβάνει (catches) και διαχειρίζεται ένα exception. Περιέχει: • Ξεκινά με το keyword catch • Το exception parameter σε παρένθεση, το οποίο ορίζει τον τύπο του exception και δίνει τη δυνατότητα στο catch block να αλληλοεπιδράσει στο exception αντικείμενο που έχει συλλεχθεί • Κώδικας σε μπλοκ με curly braces το οποίο εκτελείται όταν ο αντίστοιχος συγκεκριμένος τύπος exception συμβεί Matching catch block – ο τύπος του exception parameter αντιστοιχεί στον τύπο του thrown exception ακριβώς ή είναι υποτάξη του Uncaught exception – ένα exception που συμβαίνει χωρίς να υπάρχουν αντίστοιχα catch blocks που να ταιριάζουν • Αναγκάζουν ένα πρόγραμμα να τερματίσει την εκτέλεση του αν έχει μόνο ένα thread, ή αν υπάρχουν περισσότερα threads να τερματιστεί μόνο το ενεργό thread με ενδεχόμενες συνέπειες στο υπόλοιπο πρόγραμμα. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 12 Μοντέλο Τερματισμού Διαχείρισης εξαιρέσεων (Termination Model of Exception Handling) Όταν ένα exception συμβεί: • η εκτέλεση του try block τερματίζεται άμεσα • ο έλεγχος του προγράμματος μεταφέρεται στο 1ο catch block που ταιριάζει στο exception που προέκυψε Αφού γίνει διαχείριση του exception: • Βάσει του Μοντέλου τερματισμού (termination model of exception handling) ο έλεγχος του προγράμματος δεν επιστρέφει στο σημείο όπου προέκυψε η εξαίρεση αφού το try block έχει λήξει • Η ροή ελέγχου του προγράμματος προχωρά με την πρώτη εντολή μετά το τελευταίο catch block Εντολή try: αποτελείται από το try block και τα αντίστοιχα catch και/ή finally blocks ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 13 Χρήση του throws throws – ορίζει τα exceptions τα οποία μπορεί να προκύψουν σε μία μέθοδο • Εμφανίζεται μετά τις παραμέτρους μιας μεθόδου και πριν το σώμα της • Περιέχει μία λίστα από exceptions τα οποία διαχωρίζονται από κόμματα. • Exceptions μπορούν να προκύψουν (can be thrown) από εντολές στο σώμα της μεθόδου ή από μεθόδους που καλούνται από το σώμα της μεθόδου • Exceptions μπορεί να είναι κάποιου από τους τύπους που περιέχονται στη λίστα του throws ή υποτάξεις εκείνων ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 14 1 // Fig. 13.2: DivideByZeroWithExceptionHandling.java 2 3 // An exception-handling example that checks for divide-by-zero. import java.util.InputMismatchException; 4 import java.util.Scanner; 5 6 public class DivideByZeroWithExceptionHandling 7 { 8 9 throws clause specifies that method quotient may throw an ArithmeticException // demonstrates throwing an exception when a divide-by-zero occurs public static int quotient( int numerator, int denominator ) throws ArithmeticException 10 11 12 { 13 14 15 16 } // end method quotient return numerator / denominator; // possible division by zero public static void main( String args[] ) { 17 18 19 Scanner scanner = new Scanner( System.in ); // scanner for input boolean continueLoop = true; // determines if more input is needed 20 do 21 { Repetition statement loops until try block completes successfully 22 try // read two numbers and calculate quotient 23 { try block attempts to read input and perform division 24 25 System.out.print( "Please enter an integer numerator: " ); int numerator = scanner.nextInt(); 26 System.out.print( "Please enter an integer denominator: " ); 27 28 int denominator = scanner.nextInt(); Retrieve input; InputMismatchException thrown if input not valid integers15 ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής Call method quotient, which may throw ArithmeticException 29 int result = quotient( numerator, denominator ); 30 System.out.printf( "\nResult: %d / %d = %d\n", numerator, 31 32 denominator, result ); continueLoop = false; // input successful; end looping 33 34 } // end try catch ( InputMismatchException inputMismatchException ) 35 36 { Catching InputMismatchException System.err.printf( "\nException: %s\n", inputMismatchException ); 37 38 scanner.nextLine(); // discard input so user can try again 39 System.out.println( Read invalid input but do nothing with it 40 41 42 Notify user of "You must enter integers. Please try again.\n" ); error made } // end catch catch ( ArithmeticException arithmeticException ) Catching ArithmeticException (user 43 { has entered zero for denominator) 44 System.err.printf( "\nException: %s\n", arithmeticException ); 45 46 System.out.println( "Zero is an invalid denominator. Please try again.\n" ); 47 48 49 } // end catch } while ( continueLoop ); // end do...while } // end main 50 } // end class DivideByZeroWithExceptionHandling If line 32 was never successfully reached, loop continues and user can try again ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 16 Outline Please enter an integer numerator: 100 Please enter an integer denominator: 7 Result: 100 / 7 = 14 Please enter an integer numerator: 100 Please enter an integer denominator: 0 Exception: java.lang.ArithmeticException: / by zero Zero is an invalid denominator. Please try again. Please enter an integer numerator: 100 Please enter an integer denominator: 7 Result: 100 / 7 = 14 Please enter an integer numerator: 100 Please enter an integer denominator: hello Exception: java.util.InputMismatchException You must enter integers. Please try again. Please enter an integer numerator: 100 Please enter an integer denominator: 7 Result: 100 / 7 = 14 ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 17 Χρήση των μηχανισμών διαχείρισης εξαιρέσεων (Exception Handling) Ο μηχανισμός διαχείρισης σφαλμάτων (Exception handling) έχει σκοπό τη διαχείριση σύγχρονων σφαλμάτων (synchronous errors) • Synchronous errors – συμβαίνουν όταν μία εντολή εκτελείται • (Asynchronous errors – συμβαίνουν παράλληλα και ανεξάρτητα από τη ροή ελέγχου του προγράμματος) ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 18 Οι μηχανισμοί διαχείρισης σφαλμάτων (exception handling) παρέχουν ένα μοναδικό και ομοιόμορφο τρόπο διαχείρισης των προβλημάτων που μπορεί να προκύψουν κατά την εκτέλεση ενός προγράμματος. Αυτό βοηθά προγραμματιστές που εργάζονται σε μεγάλα προγράμματα να κατανοούν επακριβώς τον τρόπο με τον οποίο οι άλλοι προγραμματιστές διαχειρίζονται ενδεχόμενα σφάλματα (exceptions). Δεν πρέπει να χρησιμοποιούνται οι μηχανισμοί διαχείρισης σφαλμάτων (exception handling) για τον έλεγχο της ροής ενός αλγορίθμου ή προγράμματος, ώστε να μην προκαλείται σύγχυση. Οι μηχανισμοί διαχείρισης σφαλμάτων (exception handling) διευκολύνουν το συνδυασμό στοιχείων λογισμικού (software components) για να μπορούν να εργαστούν μαζί επικοινωνώντας μεταξύ τους σχετικά με ενδεχόμενα προβλήματα (exceptions). ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 19 Ιεραρχία Διαχείρισης Σφαλμάτων (Java Exception Hierarchy) Όλα τα exceptions κληρονομούν είτε κατευθείαν είτε μέσω υποτάξεων από την τάξη Exception Οι Exception τάξεις και υποτάξεις διαμορφώνουν μία κληρονομική ιεραρχία η οποία μπορεί να επεκταθεί κατάλληλα Η τάξη Throwable είναι υπερτάξη της τάξης Exception • Μόνο Throwable αντικείμενα μπορούν να χρησιμοποιηθούν με τους μηχανισμούς διαχείρισης σφαλμάτων (exception-handling mechanisms) • Η τάξη Throwable έχει δύο υποτάξεις: Exception και Error o Η τάξη Exception και οι υποτάξεις της αντιπροσωπεύουν περιπτώσεις προβλημάτων (exception situations) που μπορεί να συμβούν σε ένα πρόγραμμα Java και να μπορεί να τα διαχειριστεί το πρόγραμμα. o Η τάξη Error και οι υποτάξεις της αντιπροσωπεύουν προβληματικές καταστάσεις που συνήθως δεν μπορεί να αντιμετωπίσει ένα πρόγραμμα ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 20 ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 21 Κατηγορίες Checked και Unchecked exceptions Checked exceptions (ελεγχόμενες εξαιρέσεις) • Exceptions που κληρονομούν από την τάξη Exception αλλά όχι από την τάξη RuntimeException • Ο μεταγλωττιστής υποχρεώνει μία catch-or-declare απαίτηση • Ο μεταγλωττιστής ελέγχει κάθε κλήση μεθόδου και ορισμό μεθόδου για να συμπεράνει εάν η μέθοδος ρίχνει ελεγχόμενες εξαιρέσεις. Σε τέτοιες περιπτώσεις ο μεταγλωττιστής επιβεβαιώνει ότι η ελεγχόμενη εξαίρεση (checked exception) είτε αναλαμβάνεται (is caught) είτε δηλώνεται ότι ρίχνει (throws) τη συγκεκριμένη εξαίρεση (exception). Unchecked exceptions (μη ελεγχόμενες εξαιρέσεις) • Κληρονομούν από τις τάξεις RuntimeException ή Error • Ο μεταγλωττιστής δεν ελέγχει αν η εξαίρεση αναλαμβάνεται (is caught) ή δηλώνεται ότι ρίχνει (throws) τη συγκεκριμένη εξαίρεση (exception). • Αν μία μη ελεγχόμενη εξαίρεση συμβεί χωρίς να αναληφθεί το πρόγραμμα τερματίζεται ή τρέχει με απροσδιόριστη συμπεριφορά • Μία μη ελεγχόμενη εξαίρεση αποφεύγεται με σωστό προγραμματισμό ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 22 Σημειώσεις A compilation error occurs if a method explicitly attempts to throw a checked exception (or calls another method that throws a checked exception) and that exception is not listed in that method’s throws clause. If a subclass method overrides a superclass method, it is an error for the subclass method to list more exceptions in its throws clause than the overridden superclass method does. However, a subclass’s throws clause can contain a subset of a superclass’s throws list. If your method calls other methods that explicitly throw checked exceptions, those exceptions must be caught or declared in your method. If an exception can be handled meaningfully in a method, the method should catch the exception rather than declare it. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 23 Java Exception Hierarchy catch block catches all exceptions of its type and subclasses of its type If there are multiple catch blocks that match a particular exception type, only the first matching catch block executes It makes sense to use a catch block of a superclass when all the catch blocks for that class’s subclasses will perform the same functionality Placing a catch block for a superclass exception type before other catch blocks that catch subclass exception types prevents those blocks from executing, so a compilation error occurs. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 24 finally block Programs that obtain certain resources must return them explicitly to avoid resource leaks finally block • Consists of finally keyword followed by a block of code enclosed in curly braces • Optional in a try statement • If present, is placed after the last catch block • Executes whether or not an exception is thrown in the corresponding try block or any of its corresponding catch blocks • Will not execute if the application exits early from a try block via method System.exit • Typically contains resource-release code ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 25 finally block If no exception occurs, catch blocks are skipped and control proceeds to finally block. After the finally block executes control proceeds to first statement after the finally block. If exception occurs in the try block, program skips rest of the try block. First matching the catch block executes and control proceeds to the finally block. If exception occurs and there are no matching catch blocks, control proceeds to the finally block. After the finally block executes, the program passes the exception to the next outer the try block. If catch block throws an exception, the finally block still executes. A finally block typically contains code to release resources acquired in its corresponding try block; this is an effective way to eliminate resource leaks. For example, the finally block should close any files opened in the try block. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 26 finally block Standard streams • System.out – standard output stream • System.err – standard error stream System.err can be used to separate error output from regular output System.err.println and System.out.println display data to the command prompt by default ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 27 Παράδειγμα Exceptions1.java class Exceptions1 { public static void main(String args[]) { double d[] = new double[4]; for(int j=0 ; j<d.length ; j++) d[j] = j*7.15 + 2.19 ; for(int j=0 ; j<=d.length ; j++) { try{ System.out.print( " d[" + j + "] / " + j + " = "); if(j==0) throw new DivideByZeroException(); System.out.println(d[j]/j); } ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 28 catch(ArrayIndexOutOfBoundsException e) { System.out.println("Exception: " + e.getMessage()); System.out.print("e.printStackTrace(): "); e.printStackTrace(); } catch(DivideByZeroException e) { System.out.println("Exception: " + e.getMessage()); } finally { System.out.println("Inside finally()\n"); } } System.out.println( "\n Program exiting \n"); } } ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 29 class DivideByZeroException extends ArithmeticException { DivideByZeroException() { super("Trying to divide by zero"); } } ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 30 Throwing Exceptions Using the throw Statement throw statement – used to throw exceptions Programmers can thrown exceptions themselves from a method if something has gone wrong throw statement consists of keyword throw followed by the exception object ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 31 Rethrowing Exceptions Exceptions are rethrown when a catch block decides either that it cannot process the exception or that it can only partially process it Exception is deferred to outer try statement Exception is rethrown by using keyword throw followed by a reference to the exception object ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 32 Common Programming Error If an exception has not been caught when control enters a finally block and the finally block throws an exception that is not caught in the finally block, the first exception will be lost and the exception from the finally block will be returned to the calling method. Avoid placing code that can throw an exception in a finally block. If such code is required, enclose the code in a try statement within the finally block. Good Programming Practice Java’s exception-handling mechanism is intended to remove errorprocessing code from the main line of a program’s code to improve program clarity. Do not place try... catch finally... around every statement that may throw an exception. This makes programs difficult to read. Rather, place one try block around a significant portion of your code, follow that try block with catch blocks that handle each possible exception and follow the catch blocks with a single finally block (if one is required). ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 33 1 // Fig. 13.5: UsingExceptions.java 2 3 // Demonstration of the try...catch...finally exception handling // mechanism. 4 5 public class UsingExceptions 6 7 { 8 9 10 11 public static void main( String args[] ) Call method that throws an exception { try { throwException(); // call method throwException 12 } // end try 13 14 catch ( Exception exception ) // exception thrown by throwException { 15 16 System.err.println( "Exception handled in main" ); } // end catch 17 18 doesNotThrowException(); 19 20 } // end main ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 34 21 // demonstrate try...catch...finally 22 public static void throwException() throws Exception 23 { 24 try // throw an exception and immediately catch it 25 { 26 System.out.println( "Method throwException" ); 27 throw new Exception(); // generate exception Create new Exception and throw it 28 } // end try 29 catch ( Exception exception ) // catch exception thrown in try 30 { System.err.println( 31 32 "Exception handled in method throwException" ); 33 throw exception; // rethrow for further processing Throw previously created Exception 34 // any code here would not be reached 35 36 finally block executes even though exception is rethrown in catch block 37 } // end catch 38 finally // executes regardless of what occurs in try...catch 39 { 40 41 System.err.println( "Finally executed in throwException" ); } // end finally 42 43 44 // any code here would not be reached, exception rethrown in catch ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 35 45 46 } // end method throwException 47 // demonstrate finally when no exception occurs 48 49 public static void doesNotThrowException() { 50 try // try block does not throw an exception 51 52 { 53 54 55 56 } // end try catch ( Exception exception ) // does not execute { System.err.println( exception ); 57 58 59 } // end catch finally // executes regardless of what occurs in try...catch { 60 61 62 System.out.println( "Method doesNotThrowException" ); System.err.println( "Finally executed in doesNotThrowException" ); } // end finally finally block executes even though no exception is thrown 63 64 System.out.println( "End of method doesNotThrowException" ); 65 } // end method doesNotThrowException 66 } // end class UsingExceptions Method throwException Exception handled in method throwException Finally executed in throwException Exception handled in main Method doesNotThrowException Finally executed in doesNotThrowException End of method doesNotThrowException ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 36 Stack Unwinding Stack unwinding – When an exception is thrown but not caught in a particular scope, the method-call stack is “unwound,” and an attempt is made to catch the exception in the next outer try block. When unwinding occurs: • The method in which the exception was not caught terminates • All local variables in that method go out of scope • Control returns to the statement that originally invoked the method – if a try block encloses the method call, an attempt is made to catch the exception. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 37 Stack Unwinding Call-stack Searching unsuccessfully the call-stack to find a proper exception handler ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 38 1 // Fig. 13.6: UsingExceptions.java 2 // Demonstration of stack unwinding. 3 4 public class UsingExceptions 5 { 6 public static void main( String args[] ) 7 { 8 try // call throwException to demonstrate stack unwinding 9 { throwException(); 10 Call method that throws an exception 11 } // end try 12 catch ( Exception exception ) // exception thrown in throwException 13 { 14 15 16 17 System.err.println( "Exception handled in main" ); } // end catch } // end main Catch exception that may occur in the above try block, including the call to method throwException ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 39 18 // throwException throws exception that is not caught in this method 19 public static void throwException() throws Exception 20 { 21 try // throw an exception and catch it in main 22 { 23 System.out.println( "Method throwException" ); 24 throw new Exception(); // generate exception Method throws exception 25 } // end try 26 catch ( RuntimeException runtimeException ) // catch incorrect type 27 { System.err.println( 28 "Exception handled in method throwException" ); 29 30 } // end catch 31 finally // finally block always executes 32 { 33 34 35 Throw new exception; Exception not caught in current try block, so handled in outer try block System.err.println( "Finally is always executed" ); } // end finally } // end method throwException 36 } // end class UsingExceptions Method throwException Finally is always executed Exception handled in main finally block executes before control returns to outer try block ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 40 printStackTrace, getStackTrace and getMessage Methods in class Throwable retrieve more information about an exception • printStackTrace – outputs stack trace to standard error stream • getStackTrace – retrieves stack trace information as an array of StackTraceElement objects; enables custom processing of the exception information • getMessage – returns the descriptive string stored in an exception An exception that is not caught in an application causes Java’s default exception handler to run. This displays the name of the exception, a descriptive message that indicates the problem that occurred and a complete execution stack trace. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 41 1 // Fig. 13.7: UsingExceptions.java 2 // Demonstrating getMessage and printStackTrace from class Exception. 3 4 public class UsingExceptions 5 { 6 public static void main( String args[] ) 7 { 8 try 9 { Call to method1, method1 calls method2, method2 calls method3 and method3 throws a new Exception method1(); // call method1 10 Display descriptive string of exception thrown in method3 11 } // end try 12 catch ( Exception exception ) // catch exception thrown in method1 13 { 14 System.err.printf( "%s\n\n", exception.getMessage() ); 15 exception.printStackTrace(); // print exception stack trace 16 Display stack trace for exception thrown in method3 17 // obtain the stack-trace information 18 19 StackTraceElement[] traceElements = exception.getStackTrace(); Retrieve stack information as an array of StackTraceElement objects ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 42 20 System.out.println( "\nStack trace from getStackTrace:" ); 21 System.out.println( "Class\t\tFile\t\t\tLine\tMethod" ); 22 23 // loop through traceElements to get exception description 24 for ( StackTraceElement element : traceElements ) 25 { 26 System.out.printf( "%s\t", element.getClassName() ); 27 System.out.printf( "%s\t", element.getFileName() ); 28 System.out.printf( "%s\t", element.getLineNumber() ); 29 System.out.printf( "%s\n", element.getMethodName() ); } // end for 30 } // end catch 31 32 } // end main 33 Retrieve class, file, line number , method name for current StackTraceElement 34 // call method2; throw exceptions back to main 35 public static void method1() throws Exception 36 { 37 38 39 method2(); } // end method method1 method1 calls method2, method2 calls method3 and method3 throws an Exception ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 43 40 // call method3; throw exceptions back to method1 41 public static void method2() throws Exception 42 { 44 method2 calls method3, which throws an Exception method3(); 43 } // end method method2 45 46 // throw Exception back to method2 47 public static void method3() throws Exception 48 { 49 50 Exception created and thrown throw new Exception( "Exception thrown in method3" ); } // end method method3 51 } // end class UsingExceptions Exception thrown in method3 java.lang.Exception: Exception thrown in method3 at UsingExceptions.method3(UsingExceptions.java:49) at UsingExceptions.method2(UsingExceptions.java:43) at UsingExceptions.method1(UsingExceptions.java:37) at UsingExceptions.main(UsingExceptions.java:10) Stack trace from getStackTrace: Class File UsingExceptions UsingExceptions.java UsingExceptions UsingExceptions.java UsingExceptions UsingExceptions.java UsingExceptions UsingExceptions.java Line 49 43 37 10 Method method3 method2 method1 main ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 44 Declaring New Exception Types You can declare your own exception classes that are specific to the problems that can occur when another program uses your reusable classes New exception class must extend an existing exception class Typically contains only two constructors • One takes no arguments, passes a default exception messages to the superclass constructor • One that receives a customized exception message as a string and passes it to the superclass constructor When defining your own exception type, study the existing exception classes in the Java API and try to extend a related exception class. For example, if you are creating a new class to represent when a method attempts a division by zero, you might extend class ArithmeticException because division by zero occurs during arithmetic. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 45 The new exception class should be a checked exception (i.e., extend Exception but not RuntimeException) if possible clients should be required to handle the exception. The client application should be able to reasonably recover from such an exception. The new exception class should extend RuntimeException if the client code should be able to ignore the exception (i.e., the exception is an unchecked exception). By convention, all exception-class names should end with the word Exception. ΠΠΜ 500: Προχωρημένη Ανάπτυξη Λογισμικού Εφαρμογών Μηχανικής 46