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:20] gthanos [Πυροδότηση μιας εξαίρεσης] |
java:exceptions_intro [2017/03/10 11:15] gthanos |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== | + | ====== |
| - | Σε αυτή την ενότητα θα αναφερθούμε σε αντικείμενα τα οποία δημιουργούνται κατά την ροή εκτέλεσης ενός προγράμματος, | + | Σε αυτή την ενότητα θα αναφερθούμε σε αντικείμενα τα οποία δημιουργούνται κατά την ροή εκτέλεσης ενός προγράμματος, |
| - | Για να διασφαλίσουμε ότι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός, | + | Για να διασφαλίσουμε ότι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός, |
| ====== Αντικείμενο της εξαίρεσης (exception object) ====== | ====== Αντικείμενο της εξαίρεσης (exception object) ====== | ||
| - | Οτιδήποτε υπάρχει στην γλώσσα Java δεν είναι κάτι διαφορετικό απο αντικείμενο. Έτσι, ακόμη και οι εξαιρέσεις που μπορούν να προκληθούν, | ||
| - | Σε αυτό το σημείο ας δούμε ένα πολύ απλό και συχνό λάθος που μπορεί να προκύψει αν δεν το προσέξουμε εμείς ή ο χρήστης. | + | Κάθε εξαίρεση που μπορεί να προκληθεί παράγει ένα αντικείμενο το οποίο περιέχει όλες τις πληροφορίες που έχουν να κάνουν με το λάθος το οποίο έχει προκύψει, |
| + | |||
| + | Σε αυτό το σημείο ας δούμε ένα πολύ απλό και συχνό λάθος που μπορεί να προκύψει αν δεν | ||
| <code java TestDivideByZero.java> | <code java TestDivideByZero.java> | ||
| Line 37: | Line 38: | ||
| Τι θα συμβεί στο παραπάνω πρόγραμμα αν ο 2ος αριθμός που θα δώσει ο χρήστης είναι 0; Επίσης αν ο χρήστης δεν δώσει αριθμό σαν είσοδο αλλά γράμμα; | Τι θα συμβεί στο παραπάνω πρόγραμμα αν ο 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> | ||
| - | import java.io.*; | ||
| - | import java.util.Scanner; | ||
| - | public class TestDivideByZero { | ||
| - | |||
| - | | ||
| - | int x, y, 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(); | ||
| - | | ||
| - | try { | ||
| - | | ||
| - | | ||
| - | } catch (ArithmeticException ae) { | ||
| - | | ||
| - | if(y == 0){ | ||
| - | System.out.println(" | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | Όπως βλέπουμε έχουμε το προηγούμενο παράδειγμα, | ||
| - | |||
| - | === Ανοίγοντας ένα αρχείο για διάβασμα === | ||
| - | |||
| - | Παρακάτω δίνεται ένα πιο σύνθετο παράδειγμα μία μεθόδου που διαβάζει ένα αρχείο κειμένου και το επιστρέφει στη μορφή ενός String. | ||
| - | |||
| - | <code java WholeFileReader.java> | ||
| - | 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 μας δίνει την δυνατότητα να μην διαχειριστούμε την εξαίρεση μέσα στην μέθοδο που προκύπτει, | ||
| - | |||
| - | Σε προηγούμενο παράδειγμα αναφερθήκαμε στη PrintWriter class και βάλαμε ένα try-catch block για να διαχειριστούμε τη πιθανή δημιουργία μας εξαίρεσης. | ||
| - | |||
| - | <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); | ||
| - | } | ||
| - | return strDocument.toString(); | ||
| - | } | ||
| - | | ||
| - | finally { | ||
| - | if( fReader != null) { | ||
| - | try { | ||
| - | System.out.println(" | ||
| - | 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(" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | } | ||
| - | </ | ||
| - | |||
| - | Στον παραπάνω κώδικα βλέπουμε την περίπτωση στην οποία δεν διαχειριζόμαστε την εξαίρεση εντός της μεθόδου '' | ||
| - | |||
| - | ====== Πυροδότηση μιας εξαίρεσης ====== | ||
| - | Στις προηγούμενες ενότητες είδαμε τον τρόπο με τον οποίο χειριζόμαστε μια εξαίρεση. Μέχρι αυτό το σημείο έχουμε αναφερθεί σε εξαιρέσεις που παρέχονται από κλάσεις του συστήματος. Πως όμως δημιουργούνται αυτές οι εξαιρέσεις και πως και εμείς μπορούμε να καλέσουμε μια εξαίρεση; | ||
| - | |||
| - | Επανερχόμενοι στο παράδειγμα ανάγνωσης ενός αρχείου ας υποθέσουμε ότι θέλουμε να δημιουργούμε μία εξαίρεση αν το αρχείο είναι άδειο, δηλ δεν περιέχει κανένα χαρακτήρα. Για τον σκοπό αυτό δημιουργούμε ένα νέο τύπο εξαίρεσης με όνομα '' | ||
| - | |||
| - | <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(" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | } | ||
| - | </ | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||