Πανεπιστήμιο Πειραιά Τμήμα Ψηφιακών Συστημάτων Αντικειμενοστρεφής Προγραμματισμός 30/5/2016 Δρ. Ανδριάνα Πρέντζα Αναπληρώτρια Καθηγήτρια aprentza@unipi.gr
Χειρισμός Εξαιρέσεων Εξαίρεση (Exception) ένδειξη ότι συμβαίνει ένα πρόβλημα κατά την εκτέλεση ενός προγράμματος Διαχείριση εξαιρέσεων (Exception handling) επίλυση και αντιμετώπιση των εξαιρέσεων που ΕΝΔΕΧΕΤΑΙ να να συμβούν, έτσι ώστε το πρόγραμμα να συνεχίσει και να τερματίσει ομαλά Η διαχείριση εξαιρέσεων επιτρέπει στους προγραμματιστές να δημιουργήσουν προγράμματα στιβαρά και ανθεκτικά στα σφάλματα
...Εισαγωγή Παραδείγματα ArrayIndexOutOfBoundsException προσπάθεια προσπέλασης στοιχείου εκτός ορίων ενός πίνακα NullPointerException όταν μια αναφορά null χρησιμοποιείται εκεί που αναμένεται ένα αντικείμενο ArithmeticException προσπάθεια διαίρεσης με το μηδέν...
Παράδειγμα: Διαίρεση με το μηδέν χωρίς διαχείριση εξαίρεσης Προκληθείσα εξαίρεση (Thrown exception) η εξαίρεση που συνέβη ArithmeticException μπορεί να προκύψει από διάφορα αριθμητικά προβλήματα InputMismatchException συμβαίνει όταν η μέθοδος nextint της Scanner λαμβάνει ένα string που δεν αναπαριστά έναν έγκυρο integer
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 public static int quotient( int numerator, int denominator ) 9 { 10 return numerator / denominator; // possible division by zero 11 } // end method quotient 12 13 public static void main( String args[] ) 14 { 15 Scanner scanner = new Scanner( System.in ); // scanner for input 16 17 System.out.print( "Please enter an integer numerator: " ); 18 int numerator = scanner.nextint(); 19 System.out.print( "Please enter an integer denominator: " ); 20 int denominator = scanner.nextint(); 21 22 int result = quotient( numerator, denominator ); 23 System.out.printf( 24 "\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
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)
...Παράδειγμα: Διαίρεση με το μηδέν χωρίς διαχείριση εξαίρεσης Με τη διαχείριση εξαιρέσεων, το πρόγραμμα εντοπίζει (catches) και χειρίζεται (handles) την εξαίρεση
Το μπλοκ try try block εσωκλείνει κώδικα που μπορεί να προκαλέσει (throw) μια εξαίρεση και τον κώδικα που δεν πρέπει να εκτελεστεί αν λάβει χώρα μία εξαίρεση Αποτελείται από τη λέξη-κλειδί try ακολουθούμενη από ένα μπλοκ κώδικα εντός αγκίστρων ({})
Το μπλοκ catch catch block εντοπίζει (catch) ή «πιάνει» και χειρίζεται μια εξαίρεση. Ξεκινά με τη λέξη-κλειδί catch Περιέχει παράμετρο εξαίρεσης σε παρενθέσεις Η παράμετρος εξαίρεσης υποδεικνύει τον τύπο της εξαίρεσης και βοηθά το μπλοκ catch να αλληλεπιδράσει με το αντικείμενο της εντοπισμένης εξαίρεσης Περιέχει μπλοκ κώδικα, σε άγκιστρα, που εκτελείται όταν μια κατάλληλου τύπου εξαίρεση λάβει χώρα Μη εντοπισμένη εξαίρεση μια εξαίρεση που συμβαίνει και για την οποία δεν υπάρχουν αντίστοιχα catch μπλοκς Το πρόγραμμα τερματίζει εκτός αν τρέχει σε πολλαπλά νήματα (threads), οπότε τερματίζει μόνο το συγκεκριμένο νήμα με πιθανές συνέπειες στα άλλα
Συνήθη προγραμματιστικά σφάλματα Η τοποθέτηση κώδικα μεταξύ ενός try μπλοκ και των αντίστοιχων catch μπλοκς της είναι συντακτικό σφάλμα Κάθε μπλοκ catch μπορεί να έχει μόνο μια απλή παράμετρο ο καθορισμός παραμέτρων εξαιρέσεων ως λίστα διαχωρισμένη με κόμματα είναι συντακτικό σφάλμα Σε μία απλή εντολή try είναι σφάλμα μεταγλώττισης ο εντοπισμός του ίδιου τύπου εξαίρεσης σε δύο διαφορετικά catch μπλοκς
Μοντέλο τερματισμού Όταν λάβει χώρα μια εξαίρεση : Το try block τερματίζει αμέσως Ο έλεγχος του προγράμματος μεταφέρεται στο πρώτο από τα μπλοκ catch που ακολουθούν και στο οποίο ο τύπος παραμέτρου εξαίρεσης ταιριάζει στον τύπο της εξαίρεσης που συμβαίνει (matching catch block) Μετά το χειρισμό της εξαίρεσης: Μοντέλο τερματισμού χειρισμού εξαιρέσεων Ο έλεγχος προγράμματος δε γυρνά στο σημείο πρόκλησης (throw point) διότι το try block έχει εκπνεύσει. Ο έλεγχος ροής συνεχίζει στην πρώτη εντολή μετά το τελευταίο catch μπλοκ Μοντέλο συνέχισης χειρισμού εξαιρέσεων Ο έλεγχος προγράμματος συνεχίζει αμέσως μετά τι σημείο της πρόκλησης Η εντολή try αποτελείται από το μπλοκ try και τα αντίστοιχα catch μπλοκς
Χρήση της φράσης throws throws καθορίζει τις εξαιρέσεις που μπορεί να προκαλέσει μία μέθοδος Εμφανίζεται μετά τη λίστα παραμέτρων της μεθόδου και πριν από το σώμα της Περιέχει λίστα από εξαιρέσεις που διαχωρίζονται με κόμματα Οι εξαιρέσεις μπορούν να προκληθούν από εντολές στο σώμα μιας μεθόδου ή από εντολές που καλούνται από το σώμα μιας μεθόδου Μια μέθοδος μπορεί να καλέσει τις εξαιρέσεις του τύπου που παρατίθενται στη φράση throws ή αυτές στις υποκλάσεις της
Αποφυγή λαθών Αν γνωρίζετε ότι μια μέθοδος μπορεί να προκαλέσει μια εξαίρεση, ενσωματώστε κατάλληλο κώδικα χειρισμού εξαιρέσεων στο πρόγραμμά σας Διαβάστε το online API documentation εντολή της Java για μία μέθοδο πριν τη χρησιμοποιήσετε σε ένα πρόγραμμα. Το documentation ορίζει τις εξαιρέσεις που προκαλούνται από τη μέθοδο (αν υπάρχουν) και υποδεικνύει λόγους για τους οποίους μπορούν να συμβούν τέτοιες εξαιρέσεις.
1 // Fig. 13.2: DivideByZeroWithExceptionHandling.java 2 // An exception-handling example that checks for divide-by-zero. 3 import java.util.inputmismatchexception; 4 import java.util.scanner; 5 6 public class DivideByZeroWithExceptionHandling 7 { 8 // demonstrates throwing an exception when a divide-by-zero occurs 9 public static int quotient( int numerator, int denominator ) 10 throws ArithmeticException 11 { 12 return numerator / denominator; // possible division by zero 13 } // end method quotient 14 15 public static void main( String args[] ) 16 { 17 Scanner scanner = new Scanner( System.in ); // scanner for input 18 boolean continueloop = true; // determines if more input is needed 19 20 do 21 { 22 try // read two numbers and calculate quotient 23 { 24 System.out.print( "Please enter an integer numerator: " ); 25 int numerator = scanner.nextint(); 26 System.out.print( "Please enter an integer denominator: " ); 27 int denominator = scanner.nextint(); 28 Η δήλωση επανάληψης επαναλαμβάνεται ωσότου το μπλοκ try τερματίσει επιτυχώς Η φράση throws καθορίζει ότι η μέθοδος quotient μπορεί να προκαλέσει μια ArithmeticException Το μπλοκ try επιχειρεί να διαβάσει τη είσοδο και να κάνει τη διαίρεση Ανάκτηση εισόδου. Η InputMismatc hexception προκαλείται αν η είσοδοι δεν είναι έγκυροι integers
29 int result = quotient( numerator, denominator ); 30 System.out.printf( "\nresult: %d / %d = %d\n", numerator, 31 denominator, result ); 32 continueloop = false; // input successful; end looping 33 } // end try 34 catch ( InputMismatchException inputmismatchexception ) 35 { 36 System.err.printf( "\nexception: %s\n", 37 inputmismatchexception ); 38 scanner.nextline(); // discard input so user can try again 39 System.out.println( 40 "You must enter integers. Please try again.\n" ); 41 } // end catch 42 catch ( ArithmeticException arithmeticexception ) 43 { 44 System.err.printf( "\nexception: %s\n", arithmeticexception ); 45 System.out.println( 46 "Zero is an invalid denominator. Please try again.\n" ); 47 } // end catch 48 } while ( continueloop ); // end do...while 49 } // end main 50 } // end class DivideByZeroWithExceptionHandling Αν δε φτάσουμε ποτέ επιτυχώς στη γραμμή 32, ο βρόχος συνεχίζει και ο χρήστης μπορεί να ξαναπροσπαθήσει Κλήση μεθόδου quotient, που μπορεί να προκαλέσει ArithmeticException Αν φτάσαμε σε αυτό το σημείο, η είσοδος ήταν έγκυρη και ο παρονομαστής (denominator) ήταν μη μηδενικός, όποτε ο βρόχος μπορεί να τερματίσει Εντοπισμός της εξαίρεσης InputMismatchExce ption (ο χρήστης εισήγαγε μη ακέραιη είσοδο) Παράμετροι εξαιρέσεων Διάβασμα μη έγκυρης εισόδου χωρίς καμία αντίδραση όμως Notify user of error made Εντοπισμός της εξαίρεσης ArithmeticException (ο χρήστης εισήγαγε μηδέν για παρονομαστή
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
Πηγές/Acknowledgements http://java.sun.com/j2se H. M. Deitel, P. J. Deitel, Java Προγραμματισμός, 6η έκδοση, Μ. Γκιούρδας, 2006 D. Barnes, M. Kolling, Αντικειμενοστρεφής Προγραμματισμός σε Java, Κλειδάριθμος, 2008 Βασίλης Χριστοφίδης, Αντικειμενοστρεφής Προγραμματισμός, Πανεπιστήμιο Κρήτης Κ. Τσαγκάρης, Εισαγωγή στις εφαρμογές της Java, Πανεπιστήμιο Πειραιώς Jones, Evan, Adam Marcus, and Eugene Wu. 6.092 Introduction to Programming in Java,January IAP 2010. (Massachusetts Institute of Technology: MIT OpenCourseWare), http://ocw.mit.edu (Accessed 10 Mar, 2013). License: Creative Commons BY-NC-SA Στέλιος Ξυνόγαλος, Αντικειμενοστρεφής Σχεδίαση και Προγραμματισμός, Παρουσιάσεις, 2010 Σ. Γεωργαντάκη, Μία τεχνολογικά υποστηριζόμενη διδακτική προσέγγιση για τον αντικειμενοστρεφή προγραμματισμό, Πανεπιστήμιο Πειραιώς, 2007