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/02/27 21:25]
ckonstantas
java:exceptions_intro [2015/03/02 16:56]
gthanos [Finaly Block]
Line 1: Line 1:
-====== Τι είναι η εξαίρεση(exception); ====== +====== Τι είναι η εξαίρεση (Exception); ======
-Όπως αναφέρει και το όνομα της συγκεκριμένης ενότητας,​ θα αναφερθούμε σε έναν μηχανισμό ο οποίος διαχειρίζεται γεγονότα τα οποία δεν ανήκουν στην κανονική εκτέλεση του προγράμματος αλλά συμβαίνουν απροσδόκητα. Για να διασφαλίσουμε οτι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός,​ χρησιμοποιούμε τον μηχανισμό των **εξαιρέσεων(exceptions)**.+
  
-Το βασικό πλεονέκτημα που μας ​προσδίδει η χρήση των εξαιρέσεων είναι το γεγονός οτι μπορούμε να επιλέξουμε σε ποιο σημείο ακριβώς θα διαχειριστούμε την εξαίρεση που έχει προκύψει.+Όπως ​αναφέρει ​και το όνομα ​της συγκεκριμένης ενότητας, θα αναφερθούμε ​σε αντικείμενα τα οποία δημιουργούνται κατά την ροή εκτέλεσης ενός ​προγράμματος, όταν συμβαίνει κάτι αναπάντεχο ή μη διαχειρίσιμο από το πρόγραμμα. Σε αυτές της περιπτώσεις παράγεται ένα νέο αντικείμενο που ονομάζεται "​εξαίρεση" (exception), ​με παράλληλη διακοπή της κανονικής ροής του προγράμματος μας. Ο προγραμματιστής καλείται να διαχειριστεί μέσα από ​επιπλέον κώδικα τις ​εξαιρέσεις αυτές, και να αντιμετωπίσει τα γεγονότα από τα οποία ​προέρχονται.
  
-====== Αντικείμενο της εξαίρεσης(exception object) ======+Για να διασφαλίσουμε οτι το πρόγραμμά μας θα συνεχίσει την εκτέλεσή του ακόμη και αν συμβεί ένα απροσδόκητο γεγονός,​ χρησιμοποιούμε τον μηχανισμό της διαχείρισης των **εξαιρέσεων (exceptions)**. Το βασικό πλεονέκτημα που μας προσδίδει η χρήση των εξαιρέσεων είναι το γεγονός ότι μπορούμε να επιλέξουμε σε ποιο σημείο του προγράμματος θα διαχειριστούμε την εξαίρεση που έχει προκύψει. 
 + 
 + 
 +====== Αντικείμενο της εξαίρεσης (exception object) ======
 Οτιδήποτε υπάρχει στην γλώσσα Java δεν είναι κάτι διαφορετικό απο αντικείμενο. Έτσι, ακόμη και οι εξαιρέσεις που μπορούν να προκληθούν,​ παράγουν ένα αντικείμενο το οποίο περιέχει όλες τις πληροφορίες που έχουν να κάνουν με το λάθος το οποίο έχει προκύψει όπως ο τύπος του λάθους και την κατάσταση που βρισκόταν το σύστημα όταν έγινε το λάθος αυτό. Οτιδήποτε υπάρχει στην γλώσσα Java δεν είναι κάτι διαφορετικό απο αντικείμενο. Έτσι, ακόμη και οι εξαιρέσεις που μπορούν να προκληθούν,​ παράγουν ένα αντικείμενο το οποίο περιέχει όλες τις πληροφορίες που έχουν να κάνουν με το λάθος το οποίο έχει προκύψει όπως ο τύπος του λάθους και την κατάσταση που βρισκόταν το σύστημα όταν έγινε το λάθος αυτό.
  
Line 18: Line 20:
       int y;       int y;
       int result;       int result;
 +      Scanner input = new Scanner(System.in);​
  
       System.out.print( "Enter first integer: " );       System.out.print( "Enter first integer: " );
Line 28: Line 31:
       ​       ​
       System.out.printf( "​Product is %d\n", result );       System.out.printf( "​Product is %d\n", result );
 +   }
 } }
 </​code>​ </​code>​
Line 52: Line 56:
 <code java> <code java>
 try{ try{
-   code with some exception 
-}catch (ExceptionType name) { 
  
-}catch (ExceptionType name) {+   /*  
 +    * code that may throw an exception here. 
 +    */ 
 +    
 +}catch (ExceptionTypeOne ex) { 
 + 
 +}catch (ExceptionTypeTwo ex) {
  
 } }
 </​code>​ </​code>​
  
-Εντός του try block βάζουμε τον κώδικα που μπορεί να προκύψει μια εξαίρεση. ​Στο ​catch block (το οποίο παρατηρούμε οτι μπορεί να είναι ​πάνω ​απο ένα) βάζουμε τον κώδικα που θέλουμε να εκτελεστεί όταν θα προκύψει η κάθε εξαίρεση ​της ​οποίας ο τύπος περιγράφεται στα ορίσματα του catch block. ​ Όπως τονίσαμε μπορούμε να έχουμε πάνω απο ένα catch block.  +Εντός του ​**try** block βάζουμε τον κώδικα που μπορεί να προκύψει μια εξαίρεση. ​Κάθε **catch** block ορίζει ένα διαφορετικό τύπο εξαίρεσης μέσα ​στη παρένθεση. Εάν η εξαίρεση ​που παράγεται συμπίπτει __ως προς τον ​τύπο__ της ​με ένα ​αντικείμενο που ορίζεται εντός της παρενθέσεως ενός **catch** block, τότε αυτό το block θα εκτελεστεί. Θα εκτελεστεί επομένως ο κώδικας αντιστοιχεί στον τύπο ​δεδομένων ο οποίος ​παράχθηκε από ​την εκάστοτε εξαίρεση
- +
-Ο τρόπος ​με τον οποίον λειτουργεί είναι ο εξής. Όταν προκύψει ένα αντικείμενο εξαίρεσης, ​θα εκτελέσει το πρώτο μπλοκ το οποίο ταιριάζει με τον τύπο που περιγράφεται ​στα ορίσματα (στην ​προκειμένη περίπτωση ExceptionType). Συνεπώς θα συγκρίνει τον τύπο της ​εξαίρεσης που προέκυψε με όλους ​τους τύπους ,με τη σειρά έναν προς έναν, που υπάρχουν σαν ​παράμετροι στα catch blocks, μέχρι ​να βρεί κάποιο ταίριασμα και να πραγματοποιήσει τον κώδικα που είναι μέσα στο block.+
  
 Ας δούμε ένα μικρό τμήμα κώδικα που εντοπίζει ένα είδος εξαίρεσης το οποίο συναντήσαμε και παραπάνω:​ Ας δούμε ένα μικρό τμήμα κώδικα που εντοπίζει ένα είδος εξαίρεσης το οποίο συναντήσαμε και παραπάνω:​
Line 72: Line 78:
    
    ​public static void main (String[] args) {    ​public static void main (String[] args) {
-      int x; +      int x, y, result
-      ​int y; +       
-      ​int result;+      ​Scanner input = new Scanner(System.in);
  
       System.out.print( "Enter first integer: " );       System.out.print( "Enter first integer: " );
Line 84: Line 90:
       try {       try {
            ​result = x/y;            ​result = x/y;
 +           ​System.out.printf( "​Product is %d\n", result );
       } catch (ArithmeticException ae) {       } catch (ArithmeticException ae) {
            ​System.out.println("​ArithmeticException occured!"​);​            ​System.out.println("​ArithmeticException occured!"​);​
-           if(y = 0){ +           ​if(y ​== 0){ 
-              System.out.println("​Division by zero in particular"​)+              System.out.println("​Division by zero in particular"​);
            }            }
       }       }
-      ​ +   ​ 
-      ​System.out.printf( "​Product is %d\n", result );+   }
 } }
 </​code>​ </​code>​
  
-Όπως βλέπουμε έχουμε το προηγούμενο παράδειγμα,​ εμπλουτισμένο όμως με κάποιον χειριστή(handler) ο οποίος θα αναγνωρίσει ​οτι υπάρχει ​κάποια διαίρεση με το και έτσι θα ενημερώσει τον χρήστη.+Όπως βλέπουμε έχουμε το προηγούμενο παράδειγμα,​ εμπλουτισμένο όμως με κώδικα διαχείρισης της διαίρεσης με το μηδέν. Ο κώδικας θα αναγνωρίσει ​ότι υπάρχει ​δημιουργείται ''​ArithmeticException''​ και συγκεκριμένα διαίρεση με το μηδέν ​και θα εκτυπώσει τα σχετικά μηνύματα.
  
-Ας δούμε ένα τμήμα κώδικα όπου ​θα βάζαμε αν χειριζόμασταν αρχεία αλλά ​και ​δομές δεδομένων:+Παρακάτω ​δίνεται το παράδειγμα μία συνάρτησης ​που ​διαβάζει ​ένα αρχείο κειμένου ​και ​το επιστρέφει στη ​μορφή ενός String.
  
-<code java> +<​code ​java WholeFileReader.java> 
-try {+import java.io.*;​ 
 +import java.lang.*;​
  
-} catch (IndexOutOfBoundsException e) { +public class WholeFileReader { 
-    System.err.println("​IndexOutOfBoundsException: ​" + e.getMessage()); +   
-} catch (IOException e) { +  public String readFile(String path) { 
-    System.err.println("​Caught IOException: ​" + e.getMessage()); +   
-}+    try { 
 +      File file = new File (path); 
 +      FileReader fReader = new FileReader(file);​ 
 +      BufferedReader in = new BufferedReader(fReader);​ 
 +      String inputLine;​ 
 +      StringBuffer strDocument = new StringBuffer();​ 
 +      try { 
 +        while ((inputLine = in.readLine()) != null) { 
 +          strDocument.append(inputLine);​ 
 +        } 
 +        fReader.close();​ 
 +      ​}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 "";​ 
 +    }     
 +  } 
 +   
 +  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>​
  
-Μπορούμε να καταλάβουμε ποιο είναι το πρώτο είδος εξαίρεσης που θα εντοπίσει;​ Είναι η εξαίρεση που προκύπτει όταν βγαίνουμε εκτός ορίων μιας δομής(π.χ. πίνακας).Παρατηρούμε όμως οτι υπάρχει και ένα επιπλέον block που καλύπτει και τις εξαιρέσεις που μπορούν να προκύψουν απο την είσοδο ή την έξοδο στοιχείων (παράδειγμα:​ προσπαθούμε να ανοίξουμε ένα αρχείο που δεν υπάρχει).+==== Finaly Block ====
  
-Στο παραπάνω παράδειγμα ​το μόνο που κάνουμε ​είναι να εκτυπώσουμε ένα μήνυμα οτι προέκυψε μια εξαίρεση. Προφανώς, μπορούμε και πρέπει να βάλουμε ​κώδικα ​που κάνει κάτι πιο σημαντικό ​απο ​αυτό+Εκτός από τα **catch** blocks τα οποία εκτελούνται ​όταν έχουμε κάποιο exception, μπορούμε ​να προσθέσουμε ​ένα finaly block το οποίο θα εκτελεστεί __σε κάθε ​περίπτωση__. Το finaly block θα εκτελεστεί ​ακόμη και σε περίπτωση που προκύψει μια εξαίρεση ​ενός τύπου που δεν έχουμε φροντίσει να συμπεριλάβουμε ​ή εάν ​δεν προκύψει καμία απολύτως εξαίρεση.
  
-==== Finaly Block ==== +<code java> 
-Εκτός απο τα catch blocks, μπορούμε να έχουμε ένα finaly block το οποίο θα εκτελεστεί //**πάντα**//​Ακόμη και σε περίπτωση που προκύψει μια εξαίρεση ενός τύπου που δεν έχουμε φροντίσει να συμπεριλάβουμε,​ το finaly block θα εκτελεστεί.+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();​
 +      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();​
 +    }
 +    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>​
 +
 +Ο λόγος που μπορούμε να χρησιμοποιήσουμε το finaly block είναι για να συμπεριλάβουμε κώδικα που θέλουμε να εκτελεστεί σε όλες τις περιπτώσεις,​ όπως για παράδειγμα να κλείσουμε ελεγχόμενα τα αρχεία του προγράμματος. Στο παραπάνω παράδειγμα υπάρχει ολοκληρωμένη η μέθοδος ReadFile η οποία ανοίγει ένα αρχείο κειμένου για διάβασμα. Στο //finally// block η μέθοδος κλείνει το αρχείο που άνοιξε.
 +====== Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ======
 +Στην προηγούμενη ενότητα δείξαμε πως μπορούμε να χειριστούμε μια εξαίρεση όταν προκύπτει. Υπάρχει ένας μηχανισμός που μας επιτρέπει να μην χειριστούμε την εξαίρεση στο σημείο που προκύπτει αλλά στο σημείο που καλείται η μέθοδος μεσα στην οποία θα προκύψει μια εξαίρεση.
 +
 +Σε προηγούμενο παράδειγμα αναφερθήκαμε στη PrintWriter class και βάλαμε ένα try-catch block για να διαχειριστούμε τη πιθανή δημιουργία μας εξαίρεσης. ​
  
 <code java> <code java>
-try {+ 
 +public void writeToFile() throws IOException,​IndexOutOfBoundsException{
  
   File file = new File ("​C:/​Users/​Me/​Desktop/​directory/​file.txt"​);​   File file = new File ("​C:/​Users/​Me/​Desktop/​directory/​file.txt"​);​
Line 126: Line 231:
   printWriter.close ();   printWriter.close ();
  
-} catch (IndexOutOfBoundsException e) { + 
-    System.err.println("​IndexOutOfBoundsException:​ " + e.getMessage());​ +}
-} catch (IOException e) { +
-    System.err.println("​Caught IOException:​ " + e.getMessage());​ +
-}finally { +
-    if (out != null) {  +
-        System.out.println("​Closing PrintWriter"​);​ +
-        out.close();​  +
-    } else {  +
-        System.out.println("​PrintWriter not open"​);​ +
-    }  +
-+
  
 </​code>​ </​code>​
  
-Επίσης, ένας ​λόγος που μπορούμε να χρησιμοποιήσουμε ​το finaly ​είναι ​για ​να συμπεριλάβουμε κώδικα που θέλουμε να εκτελεστεί ​για όλες τις εξαιρέσεις ​όπως ​για παράδειγμα να κλείσουμε ελεγχόμενα το πρόγραμμα.+Στον ​παραπάνω κώδικα βλέπουμε την περίπτωση στην οποία δεν διαχειριζόμαστε την εξαίρεση εντός της μεθόδου writeToFile αλλά αφήνουμε να διαχειριστεί τις εξαιρέσεις που μπορούν να προκύψουν,​ αυτός που θα καλέσει τη μέθοδο writeToFile. Το μόνο που έχουμε ​να κάνουμε, ​είναι να βάλουμε τη δεσμευμένη λέξη **throws** και δίπλα όλες τις εξαιρέσεις που μπορούν να προκύψουν εντός της μεθόδου και ​θέλουμε να τις χειριστούμε
 + 
 +====== Πυροδότηση μιας εξαίρεσης ====== 
 +Στις προηγούμενες ενότητες ​είδαμε τον τρόπο με τον οποίο χειριζόμαστε μια εξαίρεση. Μέχρι αυτό το σημείο έχουμε αναφερθεί σε εξαιρέσεις που παρέχονται απο κλάσεις του συστήματος. Πως όμως δημιουργούνται αυτές οι εξαιρέσεις ​και ​πως ​και εμείς μπορούμε να καλέσουμε μια εξαίρεση;​ 
 + 
 +Οπως τονίσαμε και ​παραπάνω η εξαίρεση είναι και αυτή ένα αντικείμενο. Για να καλέσουμε ένα αντικείμενο εξαίρεσης το μόνο που έχουμε ​να κάνουμε είναι να βάλουμε τη δεσμευμένη λέξη **throw** και δίπλα το αντικείμενο της εξαίρεσης που θέλουμε να καλέσουμε. 
 + 
 +<code java> 
 +public Object pop() { 
 +    Object obj; 
 + 
 +    if (size == 0) { 
 +        throw new EmptyStackException();​ 
 +    } 
 + 
 +    obj = objectAt(size - 1); 
 +    setObjectAt(size - 1, null); 
 +    size--; 
 +    return obj; 
 +
 +</​code>​  
 + 
 +Στο παραπάνω παράδειγμα έχουμε δημιουργήσει μια μέθοδο η οποία βγάζει ένα αντικείμενο απο μια stack και το επιστρέφει. Θέλουμε σε περίπτωση που δεν υπάρχει κάποιο ​αντικείμενο στη stack και καλέσουμε pop να πυροδοτηθεί μια εξαίρεση 
  
-Στο παραπάνω παράδειγμα υπάρχει ολοκληρωμένο ένα μικρό τμήμα κώδικα που ανοίγει ένα αρχείο,​ γράφει κάτι και μετά το κλείνει. ​ 
  
  
    
java/exceptions_intro.txt · Last modified: 2019/04/20 05:02 by gthanos