This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
|
java:exceptions_intro [2015/03/03 07:56] gthanos [Πυροδότηση μιας εξαίρεσης] |
java:exceptions_intro [2018/03/12 07:50] gthanos |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== | + | ====== |
| - | Σε αυτή την ενότητα θα αναφερθούμε σε αντικείμενα τα οποία δημιουργούνται κατά την ροή εκτέλεσης ενός προγράμματος, | + | Σε αυτή την ενότητα θα αναφερθούμε σε αντικείμενα τα οποία δημιουργούνται κατά την ροή εκτέλεσης ενός προγράμματος, |
| - | Για να διασφαλίσουμε ότι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός, | + | Για να διασφαλίσουμε ότι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός, |
| ====== Αντικείμενο της εξαίρεσης (exception object) ====== | ====== Αντικείμενο της εξαίρεσης (exception object) ====== | ||
| - | Οτιδήποτε υπάρχει στην γλώσσα Java δεν είναι κάτι διαφορετικό απο αντικείμενο. Έτσι, ακόμη και οι εξαιρέσεις που μπορούν να προκληθούν, | ||
| - | Σε αυτό το σημείο ας δούμε ένα πολύ απλό και συχνό λάθος | + | Κάθε εξαίρεση που |
| - | <code java TestDivideByZero.java> | + | Σε αυτό το σημείο ας δούμε ένα πολύ απλό και συχνό λάθος που μπορεί να προκύψει αν δεν λάβει σχετική μέριμνα ο προγραμματιστής. |
| - | import java.io.*; | + | |
| - | import java.util.Scanner; | + | |
| - | public class TestDivideByZero { | + | |
| - | + | ||
| - | | + | |
| - | int x; | + | |
| - | int y; | + | |
| - | int result; | + | |
| - | Scanner input = new Scanner(System.in); | + | |
| - | + | ||
| - | System.out.print( "Enter first integer: " ); | + | |
| - | x = input.nextInt(); | + | |
| - | + | ||
| - | System.out.print( "Enter second integer: " ); | + | |
| - | y = input.nextInt(); | + | |
| - | + | ||
| - | result = x/y; | + | |
| - | + | ||
| - | System.out.printf( " | + | |
| - | } | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Τι θα συμβεί στο παραπάνω πρόγραμμα αν ο 2ος αριθμός που θα δώσει ο χρήστης είναι 0; Επίσης αν ο χρήστης δεν δώσει αριθμό σαν | + | |
| - | + | ||
| - | Όπως καταλαβαίνουμε, | + | |
| - | + | ||
| - | Στο παραπάνω παράδειγμα | + | |
| - | - να λάβουμε αυτό το αντικείμενο | + | |
| - | - να δούμε το λάθος που έχει | + | |
| - | - να αντιμετωπίσουμε το λάθος έτσι ώστε το πρόγραμμά μας να επιστρέψει σε μια " | + | |
| - | + | ||
| - | ====== Try - catch block ====== | + | |
| - | Στην προηγούμενη υποενότητα αναφερθήκαμε συνοπτικά στο αντικείμενο της εξαίρεσης. Εδώ θα δόυμε τον τρόπο με τον οποίο διαχειριζόμαστε τις εξαιρέσεις. | + | |
| - | ==== Exception Handler ==== | + | |
| - | Κάθε τμήμα του | + | |
| - | + | ||
| - | <code java> | + | |
| - | try{ | + | |
| - | + | ||
| - | /* | + | |
| - | * code that may throw an exception here. | + | |
| - | */ | + | |
| - | + | ||
| - | }catch (ExceptionTypeOne ex) { | + | |
| - | + | ||
| - | /* | + | |
| - | * exception handler for ExceptionTypeOne objects. | + | |
| - | */ | + | |
| - | + | ||
| - | }catch (ExceptionTypeTwo ex) { | + | |
| - | + | ||
| - | /* | + | |
| - | * exception handler for ExceptionTypeOne objects. | + | |
| - | */ | + | |
| - | + | ||
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Εντός του **try** block βάζουμε τον κώδικα που μπορεί να δημιουργηθεί μια εξαίρεση. Κάθε **catch** block ορίζει ένα διαφορετικό τύπο εξαίρεσης | + | |
| - | + | ||
| - | Ας δούμε ένα μικρό τμήμα κώδικα που εντοπίζει ένα είδος εξαίρεσης το οποίο συναντήσαμε και παραπάνω: | + | |
| <code java TestDivideByZero.java> | <code java TestDivideByZero.java> | ||
| Line 81: | Line 18: | ||
| | | ||
| - | int x, y, result; | + | int x, y; |
| - | + | | |
| - | Scanner input = new Scanner(System.in); | + | int result; |
| + | | ||
| - | | + | |
| - | x = input.nextInt(); | + | x = input.nextInt(); |
| - | | + | |
| - | y = input.nextInt(); | + | y = input.nextInt(); |
| - | + | ||
| - | try { | + | result = x/y; |
| - | result = x/y; | + | |
| - | | + | |
| - | } catch (ArithmeticException ae) { | + | |
| - | | + | |
| - | if(y == 0){ | + | |
| - | System.out.println(" | + | |
| - | } | + | |
| } | } | ||
| - | | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | Όπως βλέπουμε έχουμε το προηγούμενο παράδειγμα, εμπλουτισμένο όμως με κώδικα διαχείρισης της | + | Τι θα συμβεί στο παραπάνω πρόγραμμα αν ο 2ος αριθμός που |
| - | === Ανοίγοντας ένα αρχείο | + | Όπως καταλαβαίνουμε, θα πρέπει να προβλέψουμε όλες τις περιπτώσεις (ή τουλάχιστον τις πιο βασικές) στις οποίες ο χρήστης είτε από λάθος είτε επειδή είναι κακόβουλος θα δώσει σαν |
| - | Παρακάτω δίνεται ένα πιο σύνθετο παράδειγμα μία μεθόδου που | + | Στο παραπάνω παράδειγμα , το σύστημα θα παράξει ένα αντικείμενο που |
| + | - να λάβει το αντικείμενο | ||
| + | - να εξετάσει το λάθος που έχει προκύψει | ||
| + | - να αντιμετωπίσει το λάθος, ώστε το πρόγραμμά να επιστρέψει σε ένα σημείο από όπου μπορεί να συνεχίσει τη λειτουργία του χωρίς πρόβλημα. | ||
| - | < | + | |Προηγούμενο: |
| - | import java.io.*; | + | |
| - | import java.lang.*; | + | |
| - | public class WholeFileReader { | ||
| - | | ||
| - | public String readFile(String path) { | ||
| - | |||
| - | try { | ||
| - | File file = new File (path); | ||
| - | FileReader fReader = new FileReader(file); | ||
| - | BufferedReader in = new BufferedReader(fReader); | ||
| - | String inputLine; | ||
| - | StringBuffer strDocument = new StringBuffer(); | ||
| - | while ((inputLine = in.readLine()) != null) { | ||
| - | strDocument.append(inputLine); | ||
| - | //throw new IOException(); | ||
| - | } | ||
| - | System.out.println(" | ||
| - | fReader.close(); | ||
| - | return strDocument.toString(); | ||
| - | } | ||
| - | catch(FileNotFoundException ex) { | ||
| - | System.out.println(" | ||
| - | return ""; | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | return " | ||
| - | } | ||
| - | | ||
| - | public static void main(String args[]) { | ||
| - | WholeFileReader wfr = new WholeFileReader(); | ||
| - | try { | ||
| - | System.out.println(wfr.readFile(args[0]) ); | ||
| - | } | ||
| - | catch(IndexOutOfBoundsException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | } | ||
| - | </ | ||
| - | |||
| - | Παρατηρήστε ότι εμφανίζονται δύο **catch** blocks. Το πρώτο catch block αφορά [[http:// | ||
| - | |||
| - | <code java> | ||
| - | catch(FileNotFoundException ex) { | ||
| - | System.out.println(" | ||
| - | return ""; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | καθώς ο μη εντόπισμός αρχείου θα ενέπιπτε σε '' | ||
| - | |||
| - | Επίσης, | ||
| - | <code java> | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | catch(FileNotFoundException ex) { | ||
| - | System.out.println(" | ||
| - | return ""; | ||
| - | } | ||
| - | </ | ||
| - | Σε αυτή την περίπτωση, | ||
| - | |||
| - | Τέλος, στο παραπάνω παράδειγμα βγάλτε τα σχόλια από την γραμμή '' | ||
| - | <code java> | ||
| - | while ((inputLine = in.readLine()) != null) { | ||
| - | strDocument.append(inputLine); | ||
| - | //throw new IOException(); | ||
| - | } | ||
| - | </ | ||
| - | για να δημιουργήσετε ένα '' | ||
| - | |||
| - | ==== Finaly Block ==== | ||
| - | |||
| - | Εκτός από τα **catch** blocks τα οποία εκτελούνται όταν έχουμε κάποιο exception, μπορούμε να προσθέσουμε ένα finaly block το οποίο θα εκτελεστεί __σε κάθε περίπτωση__. Το finaly block θα εκτελεστεί στις παρακάτω περιπτώσεις: | ||
| - | * Εάν προκύψει η εξαίρεση που έχουμε φροντίσει να διαχειριστούμε (στο παρακάτω παράδειγμα FileNotFoundException). | ||
| - | * Εάν προκύψει μια εξαίρεση ενός τύπου που δεν έχουμε φροντίσει να διαχειριστούμε. | ||
| - | * Εάν δεν προκύψει καμία απολύτως εξαίρεση. | ||
| - | |||
| - | Δείτε το παρακάτω παράδειγμα όπου ενσωματώνει ένα **finally** block. | ||
| - | <code java> | ||
| - | import java.io.*; | ||
| - | import java.lang.*; | ||
| - | |||
| - | public class WholeFileReader { | ||
| - | | ||
| - | public String readFile(String path) { | ||
| - | |||
| - | FileReader fReader = null; | ||
| - | try { | ||
| - | File file = new File (path); | ||
| - | fReader = new FileReader(file); | ||
| - | BufferedReader in = new BufferedReader(fReader); | ||
| - | String inputLine; | ||
| - | StringBuffer strDocument = new StringBuffer(); | ||
| - | while ((inputLine = in.readLine()) != null) { | ||
| - | strDocument.append(inputLine); | ||
| - | //throw new IOException(); | ||
| - | } | ||
| - | fReader.close(); | ||
| - | return strDocument.toString(); | ||
| - | } | ||
| - | catch(FileNotFoundException ex) { | ||
| - | System.out.println(" | ||
| - | return ""; | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | finally { | ||
| - | if(fReader!=null) { | ||
| - | try{ | ||
| - | System.out.println(" | ||
| - | fReader.close(); | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | } | ||
| - | else { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | return ""; | ||
| - | } | ||
| - | | ||
| - | public static void main(String args[]) { | ||
| - | WholeFileReader wfr = new WholeFileReader(); | ||
| - | try { | ||
| - | System.out.println(wfr.readFile(args[0]) ); | ||
| - | } | ||
| - | catch(IndexOutOfBoundsException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | } | ||
| - | </ | ||
| - | |||
| - | Ο λόγος που συνήθως χρησιμοποιήσουμε το **finally** block είναι για να συμπεριλάβουμε κώδικα που θέλουμε να εκτελεστεί σε όλες τις περιπτώσεις, | ||
| - | |||
| - | Στο παραπάνω παράδειγμα δείτε την πορεία του κώδικα βγάζοντας τα σχόλια και βάζοντας σε σχόλια την γραμμή που δημιουργεί το '' | ||
| - | <code java> | ||
| - | while ((inputLine = in.readLine()) != null) { | ||
| - | strDocument.append(inputLine); | ||
| - | //throw new IOException(); | ||
| - | } | ||
| - | </ | ||
| - | ====== Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ====== | ||
| - | |||
| - | Στην προηγούμενη ενότητα δείξαμε πως μπορούμε να χειριστούμε μια εξαίρεση όταν προκύπτει. Η Java μας δίνει την δυνατότητα να μην διαχειριστούμε την εξαίρεση μέσα στην μέθοδο που προκύπτει, | ||
| - | |||
| - | - Κατ' | ||
| - | - Στην συνέχεια κάνουμε comment-out τις γραμμές που ελέγχουν το '' | ||
| - | - Τέλος διαχειριζόμαστε την εξαίρεση μέσα στη μέθοδο '' | ||
| - | |||
| - | <code java> | ||
| - | |||
| - | import java.io.*; | ||
| - | import java.lang.*; | ||
| - | |||
| - | public class WholeFileReader { | ||
| - | | ||
| - | public String readFile(String path) throws FileNotFoundException { | ||
| - | FileReader fReader = null; | ||
| - | | ||
| - | try { | ||
| - | File file = new File (path); | ||
| - | fReader = new FileReader(file); | ||
| - | BufferedReader in = new BufferedReader(fReader); | ||
| - | String inputLine; | ||
| - | StringBuffer strDocument = new StringBuffer(); | ||
| - | try { | ||
| - | while ((inputLine = in.readLine()) != null) { | ||
| - | strDocument.append(inputLine); | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | return strDocument.toString(); | ||
| - | } | ||
| - | /* //Remove exception from here. Handle it at a higher level | ||
| - | catch(FileNotFoundException ex) { | ||
| - | System.out.println(" | ||
| - | }*/ | ||
| - | finally { | ||
| - | if( fReader != null) { | ||
| - | try { | ||
| - | System.out.println(" | ||
| - | fReader.close(); | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | | ||
| - | public static void main(String args[]) { | ||
| - | WholeFileReader wfr = new WholeFileReader(); | ||
| - | try { | ||
| - | System.out.println(wfr.readFile(args[0]) ); | ||
| - | } | ||
| - | catch(IndexOutOfBoundsException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | catch(FileNotFoundException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | } | ||
| - | </ | ||
| - | |||
| - | Στον παραπάνω κώδικα βλέπουμε την περίπτωση στην οποία __δεν__ διαχειριζόμαστε την εξαίρεση εντός της μεθόδου '' | ||
| - | * εάν δεν διαχειριστούμε τον συγκεκριμένο τύπο Exception στην μέθοδο από την οποία καλούμε την μέθοδο με την δήλωση **throw**. | ||
| - | * ή εάν δεν έχουμε μία δήλωση **throw** για το συγκεκριμένο τύπο Exception στην δήλωση της μεθόδου από την οποία καλούμε την εν λόγω μέθοδο. | ||
| - | |||
| - | ====== Δημιουργία ενός νέου τύπου εξαίρεσης και πυροδότηση εξαίρεσης ====== | ||
| - | Στις προηγούμενες ενότητες είδαμε τον τρόπο με τον οποίο χειριζόμαστε μια εξαίρεση. Μέχρι αυτό το σημείο έχουμε αναφερθεί σε εξαιρέσεις που παρέχονται από κλάσεις του συστήματος. Πως όμως δημιουργούνται αυτές οι εξαιρέσεις και πως και εμείς μπορούμε να καλέσουμε μια εξαίρεση; | ||
| - | |||
| - | Επανερχόμενοι στο παράδειγμα ανάγνωσης ενός αρχείου ας υποθέσουμε ότι θέλουμε να δημιουργούμε μία εξαίρεση αν το αρχείο είναι άδειο, δηλ δεν περιέχει κανένα χαρακτήρα. Για τον σκοπό αυτό δημιουργούμε ένα νέο τύπο εξαίρεσης με όνομα '' | ||
| - | |||
| - | <code java EmptyFileException.java> | ||
| - | public class EmptyFileException extends java.lang.Exception { | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | Όπως τονίσαμε και παραπάνω η εξαίρεση είναι και αυτή ένα αντικείμενο. Για να καλέσουμε ένα αντικείμενο εξαίρεσης το μόνο που έχουμε να κάνουμε είναι να βάλουμε τη δεσμευμένη λέξη **throw** και δίπλα το αντικείμενο της εξαίρεσης που θέλουμε να καλέσουμε. Στο παρακάτω παράδειγμα, | ||
| - | |||
| - | <code java > | ||
| - | import java.io.*; | ||
| - | import java.lang.*; | ||
| - | |||
| - | public class WholeFileReader { | ||
| - | | ||
| - | public String readFile(String path) throws FileNotFoundException, | ||
| - | FileReader fReader = null; | ||
| - | | ||
| - | try { | ||
| - | File file = new File (path); | ||
| - | fReader = new FileReader(file); | ||
| - | BufferedReader in = new BufferedReader(fReader); | ||
| - | String inputLine; | ||
| - | StringBuffer strDocument = new StringBuffer(); | ||
| - | try { | ||
| - | while ((inputLine = in.readLine()) != null) { | ||
| - | strDocument.append(inputLine); | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | System.out.println(" | ||
| - | System.exit(1); | ||
| - | } | ||
| - | if( strDocument.toString().isEmpty() ) { | ||
| - | throw new EmptyFileException(); | ||
| - | } | ||
| - | return strDocument.toString(); | ||
| - | } | ||
| - | | ||
| - | finally { | ||
| - | if( fReader != null) { | ||
| - | try { | ||
| - | // | ||
| - | fReader.close(); | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | System.out.println(" | ||
| - | System.out.println(" | ||
| - | System.exit(1); | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | | ||
| - | public static void main(String args[]) { | ||
| - | WholeFileReader wfr = new WholeFileReader(); | ||
| - | try { | ||
| - | System.out.println(wfr.readFile(args[0]) ); | ||
| - | } | ||
| - | catch(IndexOutOfBoundsException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | catch(FileNotFoundException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | catch(EmptyFileException ex) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | } | ||
| - | </ | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||