java:exceptions_intro

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
java:exceptions_intro [2015/03/02 16:33]
gthanos [Exception Handler]
java:exceptions_intro [2015/03/03 06:05]
gthanos [Αντικείμενο της εξαίρεσης (exception object)]
Line 1: Line 1:
 ====== Τι είναι η εξαίρεση (Exception);​ ====== ====== Τι είναι η εξαίρεση (Exception);​ ======
  
-Όπως αναφέρει και το όνομα ​της συγκεκριμένης ενότητας, θα αναφερθούμε σε αντικείμενα τα οποία δημιουργούνται κατά την ροή εκτέλεσης ενός προγράμματος,​ όταν συμβαίνει κάτι αναπάντεχο ή μη διαχειρίσιμο από το πρόγραμμα. Σε αυτές της περιπτώσεις παράγεται ένα νέο αντικείμενο που ονομάζεται "​εξαίρεση"​ (exception),​ με παράλληλη διακοπή της κανονικής ροής του προγράμματος μας. Ο προγραμματιστής καλείται να διαχειριστεί μέσα από επιπλέον κώδικα τις εξαιρέσεις αυτές, και ​να αντιμετωπίσει τα γεγονότα από τα οποία προέρχονται.+Σε αυτή την ενότητα θα αναφερθούμε σε αντικείμενα τα οποία δημιουργούνται κατά την ροή εκτέλεσης ενός προγράμματος,​ όταν συμβαίνει κάτι αναπάντεχο ή μη διαχειρίσιμο από το πρόγραμμα. Σε αυτές της περιπτώσεις παράγεται ένα νέο αντικείμενο που ονομάζεται "​εξαίρεση"​ (exception),​ με παράλληλη διακοπή της κανονικής ροής του προγράμματος. Ο προγραμματιστής καλείται να διαχειριστεί μέσα από επιπλέον κώδικα τις πιθανές εξαιρέσεις,​ και ​κατ' ​επέκταση να διαχειριστεί ομαλά ​τα γεγονότα από τα οποία προέρχονται.
  
-Για να διασφαλίσουμε ​οτι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός,​ χρησιμοποιούμε τον μηχανισμό ​της ​διαχείρισης των **εξαιρέσεων (exceptions)**. Το βασικό πλεονέκτημα που μας προσδίδει η χρήση των εξαιρέσεων είναι το γεγονός ότι μπορούμε να επιλέξουμε σε ποιο σημείο του προγράμματος θα διαχειριστούμε την εξαίρεση που έχει προκύψει.+Για να διασφαλίσουμε ​ότι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός,​ χρησιμοποιούμε τον μηχανισμό διαχείρισης των **εξαιρέσεων (exceptions)**. Το βασικό πλεονέκτημα που μας προσδίδει η χρήση των εξαιρέσεων είναι το γεγονός ότι μπορούμε να επιλέξουμε σε ποιο σημείο του προγράμματος θα διαχειριστούμε την εξαίρεση που έχει προκύψει.
  
  
Line 37: Line 37:
 Τι θα συμβεί στο παραπάνω πρόγραμμα αν ο 2ος αριθμός που θα δώσει ο χρήστης είναι 0; Επίσης αν ο χρήστης δεν δώσει αριθμό σαν είσοδο αλλά γράμμα;​ Τι θα συμβεί στο παραπάνω πρόγραμμα αν ο 2ος αριθμός που θα δώσει ο χρήστης είναι 0; Επίσης αν ο χρήστης δεν δώσει αριθμό σαν είσοδο αλλά γράμμα;​
  
-Όπως καταλαβαίνουμε,​ θα πρέπει να προβλέψουμε όλες τις περιπτώσεις(ή τουλάχιστον τις πιο βασικές) στις οποίες ο χρήστης είτε απο λάθος είτε επειδή είναι κακόβουλος θα δώσει σαν είσοδο κάτι το οποίο δεν είναι σωστό και θα προκαλέσει πρόβλημα.+Όπως καταλαβαίνουμε,​ θα πρέπει να προβλέψουμε όλες τις περιπτώσεις (ή τουλάχιστον τις πιο βασικές) στις οποίες ο χρήστης είτε από λάθος είτε επειδή είναι κακόβουλος θα δώσει σαν είσοδο κάτι το οποίο δεν είναι σωστό και θα προκαλέσει πρόβλημα.
  
 Προφανώς το παραπάνω παράδειγμα είναι μια μικρή κατηγορία των διαφόρων προβλημάτων που μπορούν να δημιουργηθούν και θα πρέπει να καλύψουμε με σκοπό **να μην σταματήσει η εκτέλεση του προγράμματος**. Προφανώς το παραπάνω παράδειγμα είναι μια μικρή κατηγορία των διαφόρων προβλημάτων που μπορούν να δημιουργηθούν και θα πρέπει να καλύψουμε με σκοπό **να μην σταματήσει η εκτέλεση του προγράμματος**.
Line 104: Line 104:
 Όπως βλέπουμε έχουμε το προηγούμενο παράδειγμα,​ εμπλουτισμένο όμως με κώδικα διαχείρισης της διαίρεσης με το μηδέν. Ο κώδικας θα αναγνωρίσει ότι υπάρχει δημιουργείται ''​ArithmeticException''​ και συγκεκριμένα διαίρεση με το μηδέν και θα εκτυπώσει τα σχετικά μηνύματα. Όπως βλέπουμε έχουμε το προηγούμενο παράδειγμα,​ εμπλουτισμένο όμως με κώδικα διαχείρισης της διαίρεσης με το μηδέν. Ο κώδικας θα αναγνωρίσει ότι υπάρχει δημιουργείται ''​ArithmeticException''​ και συγκεκριμένα διαίρεση με το μηδέν και θα εκτυπώσει τα σχετικά μηνύματα.
  
-Παρακάτω δίνεται το παράδειγμα μία ​συνάρτησης ​που διαβάζει ένα αρχείο κειμένου και το επιστρέφει στη μορφή ενός String. +Παρακάτω δίνεται το παράδειγμα μία ​μεθόδου που διαβάζει ένα αρχείο κειμένου και το επιστρέφει στη μορφή ενός String.
- +
-<code java WholeFileReader.java>​\+
  
 +<code java WholeFileReader.java>​
 import java.io.*; import java.io.*;
 import java.lang.*;​ import java.lang.*;​
Line 150: Line 149:
  
 } }
- 
 </​code>​ </​code>​
  
 ==== Finaly Block ==== ==== Finaly Block ====
  
-Εκτός από τα **catch** blocks τα οποία εκτελούνται όταν έχουμε κάποιο exception, μπορούμε να προσθέσουμε ένα finaly block το οποίο θα εκτελεστεί σε κάθε περίπτωση. Το finaly block θα εκτελεστεί ακόμη και σε περίπτωση που προκύψει μια εξαίρεση ενός τύπου που δεν έχουμε φροντίσει να συμπεριλάβουμε ή δεν προκύψει καμία εξαίρεση.+Εκτός από τα **catch** blocks τα οποία εκτελούνται όταν έχουμε κάποιο exception, μπορούμε να προσθέσουμε ένα finaly block το οποίο θα εκτελεστεί ​__σε κάθε περίπτωση__. Το finaly block θα εκτελεστεί ακόμη και σε περίπτωση που προκύψει μια εξαίρεση ενός τύπου που δεν έχουμε φροντίσει να συμπεριλάβουμε ή εάν ​δεν προκύψει καμία ​απολύτως ​εξαίρεση.
  
 <code java> <code java>
-try {+import java.io.*;​ 
 +import java.lang.*;​
  
-  ​File file = new File ("​C:/​Users/​Me/​Desktop/​directory/​file.txt"​); +public class WholeFileReader { 
-  ​PrintWriter printWriter ​= new PrintWriter ​(file); +   
-  ​printWriter.println ​("​hello"​); +  public String readFile(String path) { 
-  ​printWriter.close (); +    FileReader fReader = null; 
- +   
-} catch (IndexOutOfBoundsException e) { +    try { 
-    System.err.println("​IndexOutOfBoundsException: ​" + e.getMessage()); +      ​File file = new File (path); 
-} catch (IOException e) { +      ​fReader ​= new FileReader(file); 
-    System.err.println("​Caught IOException: ​" + e.getMessage()); +      ​BufferedReader in = new BufferedReader(fReader); 
-}finally { +      ​String inputLine;​ 
-    if (out != null) {  +      StringBuffer strDocument = new StringBuffer();​ 
-        System.out.println("​Closing ​PrintWriter"); +      try { 
-        out.close();  +        while ((inputLine = in.readLine()) != null) { 
-    } else {  +          strDocument.append(inputLine); 
-        System.out.println("​PrintWriter not open"); +        } 
-    }  +         
-+      ​} 
 +      ​catch(IOException ex) { 
 +        System.out.println("​IOException occured while reading from file "+path); 
 +        System.out.println("​Exiting..."​)
 +        System.exit(1); 
 +            
 +      return strDocument.toString();​ 
 +    } 
 +    ​catch(FileNotFoundException ex) { 
 +      System.out.println("​The specified file was not found at "​+ ​path); 
 +      ​return "";​ 
 +    ​} 
 +    ​finally { 
 +      if( fReader ​!= null) { 
 +        ​try { 
 +          ​System.out.println("​Closing ​file"); 
 +          fReader.close(); 
 +        ​}  
 +        catch(IOException ex) { 
 +          System.out.println("​IOException occured while reading from file "+path); 
 +          System.out.println("​Exiting..."​);​ 
 +          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("​No file has been specified!\n"); 
 +    } 
 +  }
  
 +}
 </​code>​ </​code>​
  
-Ένας ​λόγος που μπορούμε να χρησιμοποιήσουμε το finaly block είναι για να συμπεριλάβουμε κώδικα που θέλουμε να εκτελεστεί σε όλες τις περιπτώσεις,​ όπως για παράδειγμα να κλείσουμε ελεγχόμενα τα αρχεία του προγράμματος. Στο παραπάνω παράδειγμα ​υπάρχει ολοκληρωμένο ένα μικρό τμήμα κώδικα που ​ανοίγει ένα ​αρχείογράφει κάτι και μετά το κλείνει το αρχείο που άνοιξε.+Ο λόγος που μπορούμε να χρησιμοποιήσουμε το finaly block είναι για να συμπεριλάβουμε κώδικα που θέλουμε να εκτελεστεί σε όλες τις περιπτώσεις,​ όπως για παράδειγμα να κλείσουμε ελεγχόμενα τα αρχεία του προγράμματος. Στο παραπάνω παράδειγμα παραλάσεται η μέθοδος ReadFile του προηγούμενου παραδείγματος, ​ώστε στο //finally// block η μέθοδος κλείνει το αρχείο ​που ​άνοιξε. Η διαφορά σε σχέση με την προηγούμενη μέθοδο είναι ότι ακόμη ​και ​εάν δημιουργηθεί ένα exception ​την ώρα που διαβάζουμε η ροή ​του προγράμματος θα περάσει από το finally block και το αρχείο θα κλείσει. Αυτό δεν ισχύει για το προηγούμενο παράδειγμα.
 ====== Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ====== ====== Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ======
-Στην προηγούμενη ενότητα δείξαμε πως μπορούμε να χειριστούμε μια εξαίρεση όταν προκύπτει. ​Υπάρχει ένας μηχανισμός που μας επιτρέπει ​να μην χειριστούμε την εξαίρεση στο σημείο που προκύπτει αλλά στο σημείο που καλείται η μέθοδος μεσα στην οποία θα προκύψει μια εξαίρεση.+ 
 +Στην προηγούμενη ενότητα δείξαμε πως μπορούμε να χειριστούμε μια εξαίρεση όταν προκύπτει. ​Η Java μας δίνει την δυνατότητα ​να μην ​διαχειριστούμε την εξαίρεση ​μέσα στην μέθοδο που προκύπτειαλλά ​να σε κάποια άλλη μέθοδο πιο πάνω ​που καλεί την μέθοδο ​που προκύπτει. Ας ξαναδούμε το προηγούμενο παράδειγμα ελαφρά παραλλαγμένο
  
 Σε προηγούμενο παράδειγμα αναφερθήκαμε στη PrintWriter class και βάλαμε ένα try-catch block για να διαχειριστούμε τη πιθανή δημιουργία μας εξαίρεσης. ​ Σε προηγούμενο παράδειγμα αναφερθήκαμε στη PrintWriter class και βάλαμε ένα try-catch block για να διαχειριστούμε τη πιθανή δημιουργία μας εξαίρεσης. ​
Line 188: Line 225:
 <code java> <code java>
  
-public void writeToFile() throws IOException,​IndexOutOfBoundsException{ +import java.io.*
- +import java.lang.*;
-  File file = new File ("​C:/​Users/​Me/​Desktop/​directory/​file.txt"​);​ +
-  PrintWriter printWriter = new PrintWriter ("file.txt")+
-  ​printWriter.println ("​hello"​);​ +
-  printWriter.close ();+
  
 +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("​IOException occured while reading from file "​+path);​
 +        System.out.println("​Exiting..."​);​
 +        System.exit(1);​
 +      }      ​
 +      return strDocument.toString();​
 +    }
 +    ​
 +    finally {
 +      if( fReader != null) {
 +        try {
 +          System.out.println("​Closing file"​);​
 +          fReader.close();​
 +        } 
 +        catch(IOException ex) {
 +          System.out.println("​IOException occured while reading from file "​+path);​
 +          System.out.println("​Exiting..."​);​
 +          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("​No file has been specified!\n"​);​
 +    }
 +    catch(FileNotFoundException ex) {
 +      System.out.println("​The specified file was not found at "+ args[0]);
 +    }
 +  }
  
 } }
- 
 </​code>​ </​code>​
  
-Στον παραπάνω κώδικα βλέπουμε την περίπτωση στην οποία δεν διαχειριζόμαστε την εξαίρεση εντός της μεθόδου ​writeToFile ​αλλά αφήνουμε να διαχειριστεί τις εξαιρέσεις που ​μπορούν να προκύψουν, αυτός που θα καλέσει τη μέθοδο writeToFile. Το μόνο που έχουμε να κάνουμεείναι να βάλουμε τη δεσμευμένη λέξη **throws** και ​δίπλα όλες τις εξαιρέσεις ​που μπορούν ​να προκύψουν ​εντός της μεθόδου και θέλουμε να τις χειριστούμε.+Στον παραπάνω κώδικα βλέπουμε την περίπτωση στην οποία δεν διαχειριζόμαστε την εξαίρεση εντός της μεθόδου ​''​readFile'' ​αλλά αφήνουμε να περνάμε την εξαίρεση στην ​μέθοδο που την καλεί (στην περίπτωση μας η main) και την διαχειριζόμαστε εκεί. Παρατηρήστε ότι εφόσον δεν διαχειριζόμαστε το Exception στην δήλωση της ​μεθόδου υπάρχει ​η επιπλέον δήλωση ''​throws FileNotFoundException'', ​όπου περιγράφεται ποιά Exceptions ​μπορεί να "πετάξει"​ η μέθοδος στις μεθόδους που την ​καλού. Μία ​μέθοδος μπορεί να κάνει throw περισσότερα ​του ενός Exceptions.
  
 ====== Πυροδότηση μιας εξαίρεσης ====== ====== Πυροδότηση μιας εξαίρεσης ======
Line 223: Line 308:
  
 Στο παραπάνω παράδειγμα έχουμε δημιουργήσει μια μέθοδο η οποία βγάζει ένα αντικείμενο απο μια stack και το επιστρέφει. Θέλουμε σε περίπτωση που δεν υπάρχει κάποιο αντικείμενο στη stack και καλέσουμε pop να πυροδοτηθεί μια εξαίρεση. ​ Στο παραπάνω παράδειγμα έχουμε δημιουργήσει μια μέθοδο η οποία βγάζει ένα αντικείμενο απο μια stack και το επιστρέφει. Θέλουμε σε περίπτωση που δεν υπάρχει κάποιο αντικείμενο στη stack και καλέσουμε pop να πυροδοτηθεί μια εξαίρεση. ​
 +
 +Επανερχόμενοι στο παράδειγμα ανάγνωσης ενός αρχείου ας υποθέσουμε ότι θέλουμε να δημιουργούμε μία εξαίρεση αν το αρχείο είναι άδειο, δηλ δεν περιέχει κανένα χαρακτήρα. Για τον σκοπό αυτό δημιουργούμε ένα νέο τύπο εξαίρεσης με όνομα ''​EmptyFileException''​. ​
 +
 +<code java EmptyFileException.java>​
 +public class EmptyFileException extends java.lang.Exception {
 +}
 +</​code>​
 +
 +Στην συνέχεια εάν μετά την ολοκλήρωση διαβάσματος του αρχείου αντιληφθούμε ότι το αρχείο που διαβάσαμε ήταν κενό τότε το πρόγραμμα μας πετάει το παραπάνω Exception. Δείτε τον κώδικα.
 +<code java >
 +import java.io.*;
 +import java.lang.*;​
 +
 +public class WholeFileReader {
 +  ​
 +  public String readFile(String path) throws FileNotFoundException,​ EmptyFileException {
 +    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("​IOException occured while reading from file "​+path);​
 +        System.out.println("​Exiting..."​);​
 +        System.exit(1);​
 +      }
 +      if( strDocument.toString().isEmpty() ) {
 +         throw new EmptyFileException();​
 +      }
 +      return strDocument.toString();​
 +    }
 +    ​
 +    finally {
 +      if( fReader != null) {
 +        try {
 +          //​System.out.println("​Closing file"​);​
 +          fReader.close();​
 +        } 
 +        catch(IOException ex) {
 +          System.out.println("​IOException occured while reading from file "​+path);​
 +          System.out.println("​Exiting..."​);​
 +          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("​No file has been specified!\n"​);​
 +    }
 +    catch(FileNotFoundException ex) {
 +      System.out.println("​The specified file was not found at "+ args[0]);
 +    }
 +    catch(EmptyFileException ex) {
 +      System.out.println("​File is empty!!!"​);​
 +    }
 +  }
 +
 +}
 +</​code>​
  
  
java/exceptions_intro.txt · Last modified: 2019/04/20 05:02 by gthanos