java:exceptions_try_catch_block

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
java:exceptions_try_catch_block [2017/03/10 10:34] – [Παράδειγμα 1ο - Διαίρεση με μηδέν (0)] gthanosjava:exceptions_try_catch_block [2021/03/23 07:29] (current) – [Try with resources block] gthanos
Line 30: Line 30:
 Εντός του **try** block βάζουμε τον κώδικα που μπορεί να δημιουργηθεί μια εξαίρεση. Κάθε **catch** block ορίζει ένα διαφορετικό τύπο εξαίρεσης μέσα σε παρένθεση (''ExceptionTypeOne'', ''ExceptionTypeTwo'', κλπ). Εάν η εξαίρεση που παράγεται συμπίπτει __ως προς τον τύπο__ της με ένα αντικείμενο που ορίζεται εντός της παρενθέσεως ενός **catch** block, τότε αυτό το block θα εκτελεστεί. Θα εκτελεστεί επομένως ο κώδικας αντιστοιχεί στον τύπο δεδομένων ο οποίος παράχθηκε από την εκάστοτε εξαίρεση. Εντός του **try** block βάζουμε τον κώδικα που μπορεί να δημιουργηθεί μια εξαίρεση. Κάθε **catch** block ορίζει ένα διαφορετικό τύπο εξαίρεσης μέσα σε παρένθεση (''ExceptionTypeOne'', ''ExceptionTypeTwo'', κλπ). Εάν η εξαίρεση που παράγεται συμπίπτει __ως προς τον τύπο__ της με ένα αντικείμενο που ορίζεται εντός της παρενθέσεως ενός **catch** block, τότε αυτό το block θα εκτελεστεί. Θα εκτελεστεί επομένως ο κώδικας αντιστοιχεί στον τύπο δεδομένων ο οποίος παράχθηκε από την εκάστοτε εξαίρεση.
  
-==== Παράδειγμα 1ο - Διαίρεση με μηδέν (0) ====+==== Παράδειγμα ====
  
-Ας δούμε ένα μικρό τμήμα κώδικα που εντοπίζει ένα είδος εξαίρεσης το οποίο συναντήσαμε και παραπάνω:+Στο προηγούμενο πρόγραμμα ας δούμε ποιοι τύποι εξαιρέσεων προκύπτουν με βάση τη λανθασμένη είσοδο του χρήστη. Στην περίπτωση που ο χρήστης εισάγει γράμματα αντί για ψηφία θα προκύψει μία εξαίρεση του τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/InputMismatchException.html|InputMismatchException]], ενώ στην περίπτωση που ο χρήστης πατήσει το συνδυασμό πλήκτρων CTRL+D θα προκύψει μία εξαίρεση του τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html|NoSuchElementException]]. 
  
-<code java TestDivideByZero.java+Παρατηρήστε επίσης ότι η κλάση [[https://docs.oracle.com/javase/7/docs/api/java/util/InputMismatchException.html|InputMismatchException]] είναι απόγονος της κλάσης [[https://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html|NoSuchElementException]].
-import java.io.*; +
-import java.util.Scanner; +
-public class TestDivideByZero { +
-  +
-  public static void main (String[args) { +
-    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: " ); +<code java ExceptionHandling.java> 
-    input.nextInt();+import java.util.Scanner; 
 +import java.util.NoSuchElementException; 
 +import java.util.InputMismatchException; 
 + 
 +public class ExceptionHandling { 
 +   
 +  public static void main(String []args{ 
 +     
 +    Scanner sc new java.util.Scanner(System.in);
          
     try {     try {
-        result x/y+      System.out.print("Width: "); 
-        System.out.printf( "Product is %d\n", result ); +      int width sc.nextInt(); 
-    } catch (ArithmeticException ae) { +      System.out.print("Height: "); 
-        System.out.println("ArithmeticException occured!"); +      int height = sc.nextInt(); 
-        if(y == 0){ +      double ratio = width (double)height
-          System.out.println("Division by zero in particular"); +      System.out.format("Ratio: %.2f", ratio); 
-        }+      sc.close(); 
 +    } catch(InputMismatchException ex) { 
 +      System.out.println("Input doen not match integer value."); 
 +    } catch(NoSuchElementException ex) { 
 +      System.out.println("You have closed the input from command line.");
     }     }
-    
   }   }
 } }
 </code> </code>
  
-Όπως βλέπουμε έχουμε το προηγούμενο παράδειγμα, εμπλουτισμένο όμως με κώδικα διαχείρισης της διαίρεσης με το μηδέν. Ο κώδικας θα αναγνωρίσει ότι δημιουργείται ''ArithmeticException'' και συγκεκριμένα διαίρεση με το μηδέν (0) και θα εκτυπώσει τα σχετικά μηνύματα.+<WRAP tip 80% center round> 
 +Η σειρά διαχείρισης των εξαιρέσεων έχει σημασία. Εφόσονδημιουργηθεί μία εξαίρεση, το JVM ελέγχει εάν πρόκειται για εξαίρεση του πρώτου catch block, δηλαδή του τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/InputMismatchException.html|InputMismatchException]]. Εάν δεν ταιριάζει ο τύπος στο πρώτο catch block θα πάει στο επόμενο, δηλαδή θα ελέγξει εάν είναι εξαίρεση του τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html|NoSuchElementException]].
  
-==== Παράδειγμα 2ο - Ανοίγοντας ένα αρχείο για διάβασμα ====+Εάν επιχειρήσετε να αντιμεταθέσετε τα δύο catch blocks αυτό που θα συμβεί είναι να λάβετε ένα μήνυμα λάθους από τον μεταγλωττιστή. Ο λόγος είναι ότι επειδή η κλάση InputMismatchException είναι υποκλάση της [[https://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html|NoSuchElementException]], η αντιστροφή των catch block συνεπάγεται ότι ακόμη και εάν συμβεί μία εξαίρεση του τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/InputMismatchException.html|InputMismatchException]], το σχετικό catch block δεν θα κληθεί ποτέ. Ο λόγος είναι ότι το πρώτο catch block για τη διαχείριση των εξαιρέσεων του τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html|NoSuchElementException]] θα διαχειριστεί και τις εξαιρέσεις του υπο-τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/InputMismatchException.html|InputMismatchException]]. 
 +</WRAP>
  
-Παρακάτω δίνεται ένα πιο σύνθετο παράδειγμα μία μεθόδου που διαβάζει ένα αρχείο κειμένου και το επιστρέφει στη μορφή ενός String. 
  
-<code java WholeFileReader.java> +===== Finaly Block =====
-import java.io.*; +
-import java.lang.*;+
  
-public class WholeFileReader { +Στον παραπάνω κώδικα, εμφανίζεται η κλήση της μεθόδου [[https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#close()|Scanner.close()]] στο τέλος του try block η οποία κλείνει το αντικείμενο τύπου [[https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html|Scanner]].
-   +
-  public String readFile(String path{+
  
-    try { +Η κλήση της μεθόδου όμως συμβαίνει μόνο εάν δεν παραχθεί εξαίρεση. Στην περίπτωση που παραχθεί, το αντικείμενο θα παραμείνει ενεργό, πράγμα που σε ένα μεγαλύτερο πρόγραμμα δεν θα ήταν επιθυμητό (στο παρόν πρόγραμμα, το αντικείμενο θα κλείσει αμέσως μετά με την ολοκλήρωση του προγράμματος). Για το σκοπό αυτό εισάγεται η έννοια του finally block, ως ένα block που έπεται των catch blocks και σκοπό έχει να εκτελεστεί σε όλες τις περιπτώσεις, δηλαδή: 
-      File file = new File (path); +  * Εάν προκύψει η εξαίρεση που έχουμε φροντίσει να διαχειριστούμε (στο παρακάτω παράδειγμα //FileNotFoundException//). 
-      FileReader fReader = new FileReader(file); +  * Εάν προκύψει μια εξαίρεση ενός τύπου που δεν έχουμε φροντίσει να διαχειριστούμε, εντός των υφιστάμενων catch blocks
-      BufferedReader in = new BufferedReader(fReader); +  * Εάν δεν προκύψει καμία απολύτως εξαίρεση
-      String inputLine; + 
-      StringBuffer strDocument = new StringBuffer(); +Δείτε το προηγούμενο παράδειγμα, αλλαγμένο ώστε να ενσωματώνει ένα **finally** blockΣτο παρακάτω πρόγραμμα το αντικείμενο sc θα κλείσει είτε συμβεί εξαίρεση, είτε όχι
-      while ((inputLine = in.readLine()) != null) { + 
-        strDocument.append(inputLine); +<code java ExceptionHandling.java> 
-        //throw new IOException(); +import java.util.Scanner
-      } +import java.util.NoSuchElementException
-      System.out.println("Closing File!"); +import java.util.InputMismatchException
-      fReader.close(); + 
-      return strDocument.toString(); +public class ExceptionHandling {
-    } +
-    catch(FileNotFoundException ex) { +
-      System.out.println("The specified file was not found at "+ path)+
-      return ""; +
-    }    +
-    catch(IOException ex) { +
-      System.out.println("IOException occured while reading from file "+path)+
-        +
-    return "Nothing to return.."+
-  }+
      
-  public static void main(String args[]) { +  public static void main(String []args) { 
-    WholeFileReader wfr = new WholeFileReader();+     
 +    Scanner sc = new java.util.Scanner(System.in); 
 +    
     try {     try {
-      System.out.println(wfr.readFile(args[0]) );+      System.out.print("Width: "); 
 +      int width = sc.nextInt(); 
 +      System.out.print("Height: "); 
 +      int height = sc.nextInt(); 
 +      double ratio = width / (double)height; 
 +      System.out.format("Ratio: %.2f", ratio); 
 +    } catch(InputMismatchException ex) { 
 +      System.out.println("Input doen not match integer value."); 
 +    } catch(NoSuchElementException ex
 +      System.out.println("You have closed the input from command line.");
     }     }
-    catch(IndexOutOfBoundsException ex) +    finally 
-      System.out.println("No file has been specified from command line!\n");+      sc.close();
     }     }
-  } +  } 
 } }
 </code> </code>
  
-=== Περισσότερα του ενός catch blocks - Ιεράρχιση της σειράς εμφάνισης τους ===+===== Try with resources block =====
  
-Παρατηρήστε ότι εμφανίζονται δύο **catch** blocks. Το πρώτο catch block αφορά [[http://docs.oracle.com/javase/7/docs/api/java/io/IOException.html|ΙΟException]] objects, ενώ το δεύτερο catch block αφορά [[http://docs.oracle.com/javase/7/docs/api/java/io/FileNotFoundException.html|FileNotFoundException]] objectsΑπό τους συνδέσμους που παρατίθενται θα παρατηρήσετε ότι το ''FileNotFoundException'' είναι υποκλάση του ''IOException'' και δηλώνει ότι το αρχείο δεν βρέθηκε στο filesystem.+Η Java παρέχει τη δυνατότητα για αυτόματo κλείσιμο των αντικειμένων που οι κλάσεις τους υλοποιούν το interface [[https://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html|AutoClosable]]. Οι κλάσεις που υλοποιούν το συγκεκριμένο interface συνδέονται με την διαχείριση πόρων όπως αρχεία, διάβασμα και γράψιμο στην κονσόλα, άνοιγμα υποδοχέων (sockets) ή άλλων πόρων για την επικοινωνία με απομακρυσμένα σημεία.
  
-Εάν στον παραπάνω κώδικα παραλείπονταν οι γραμμές:+Η κλάση [[https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html|Scanner]] υλοποιεί το συγκεκριμένο interface. Ας δούμε πως διαμορφώνεται ο προηγούμενος κώδικας εκμεταλλευόμενος την επιπλέον δυνατότητα του interface  [[https://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html|AutoClosable]].
  
-<code java> +<code java ExceptionHandling.java> 
-    catch(FileNotFoundException ex) { +import java.util.Scanner
-      System.out.println("The specified file was not found at "+ path)+import java.util.NoSuchElementException
-      return ""+import java.util.InputMismatchException;
-       +
-</code>+
  
-Σε αυτή την περίπτωση, ο μη εντοπισμός αρχείου θα ενέπιπτε σε ''IOException'' που αποτελεί γονική κλάση της ''FileNotFoundException''. Όταν θα συνέβαινε ένα //ΙΟException// δεν θα γνωρίζαμε εάν υπάρχει το αρχείο αλλά δεν μπορούμε να το διαβάσουμε (//IOException//) ή δεν υπάρχει καθόλου το αρχείο που θέλουμε να διαβάσουμε στο filesystem (//FileNotFoundException//). +public class ExceptionHandling {
- +
-Επίσης, δεν θα είχε κανένα νόημα να βάλουμε τα δύο παραπάνω catch blocks με ανάποδη σειρά δηλ. +
-<code java> +
-    catch(IOException ex) { +
-      System.out.println("IOException occured while opening file or reading from file "+path); +
-    }     +
-    catch(FileNotFoundException ex) { +
-      System.out.println("The specified file was not found at "+ path); +
-      return ""; +
-    } +
-</code> +
- +
-Σε αυτή την περίπτωση, εάν παραχθεί ένα //Exception// του τύπου ''FileNotFoundException'' θα διαχειριστεί από το πρώτο block που διαχειρίζεται τα ''IOExcetpions''+
- +
-=== Δημιουργία εξαίρεσης === +
- +
-Τέλος, στο παραπάνω παράδειγμα βγάλτε τα σχόλια από την γραμμή ''throw new IOException();'' +
-<code java> +
-     while ((inputLine = in.readLine()) != null) { +
-        strDocument.append(inputLine); +
-        //throw new IOException(); +
-      } +
-</code> +
-με στόχο να δημιουργήσετε ένα ''IOException'' και παρατηρήστε από τα μηνύματα που εκτυπώνονται κατά την εκτέλεση του προγράμματος την πορεία του προγράμματος. +
- +
-===== Finaly Block ===== +
- +
-Εκτός από τα **catch** blocks τα οποία εκτελούνται όταν έχουμε κάποιο exception, μπορούμε να προσθέσουμε ένα **finaly block** το οποίο θα εκτελεστεί __σε κάθε περίπτωση__. Το **finaly block** θα εκτελεστεί στις παρακάτω περιπτώσεις: +
-  * Εάν προκύψει η εξαίρεση που έχουμε φροντίσει να διαχειριστούμε (στο παρακάτω παράδειγμα //FileNotFoundException//). +
-  * Εάν προκύψει μια εξαίρεση ενός τύπου που δεν έχουμε φροντίσει να διαχειριστούμε. +
-  * Εάν δεν προκύψει καμία απολύτως εξαίρεση. +
- +
-Δείτε το παρακάτω παράδειγμα όπου ενσωματώνει ένα **finally** block. +
-<code java WholeFileReader.java> +
-import java.io.*; +
-import java.lang.*; +
- +
-public class WholeFileReader {+
      
-  public String readFile(String path) { +  public static void main(String []args) { 
- +     
-  FileReader fReader = null; +    try (Scanner sc = new java.util.Scanner(System.in))
-    try { +      System.out.print("Width: "); 
-      File file = new File (path); +      int width sc.nextInt(); 
-      fReader new FileReader(file); +      System.out.print("Height: "); 
-      BufferedReader in = new BufferedReader(fReader); +      int height = sc.nextInt()
-      String inputLine+      double ratio width / (double)height
-      StringBuffer strDocument new StringBuffer(); +      System.out.format("Ratio: %.2f", ratio); 
-      while ((inputLine = in.readLine()) != null) { +    } catch(InputMismatchException ex) { 
-        strDocument.append(inputLine); +      System.out.println("Input doen not match integer value."); 
-        //throw new IOException(); +    } catch(NoSuchElementException ex{ 
-      +      System.out.println("You have closed the input from command line.");
-      return strDocument.toString();+
     }     }
-    catch(FileNotFoundException ex) { 
-      System.out.println("The specified file was not found!"); 
-      return ""; 
-    } 
-    catch(IOException ex) { 
-      System.out.println("IOException occured while reading from file "+path); 
-    } 
-    finally { 
-      if(fReader!=null) { 
-        try{ 
-          System.out.println("Closing file!"); 
-          fReader.close(); 
-        } 
-        catch(IOException ex) { 
-          System.out.println("IOException occured while closing file "+path); 
-        } 
-      } 
-      else { 
-        System.out.println("File already closed!"); 
-      } 
-       
-    } 
-    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 from command line!\n"); 
-    } 
-  } 
- 
 } }
 </code> </code>
  
-Ο λόγος που συνήθως χρησιμοποιήσουμε το **finally** block είναι για να συμπεριλάβουμε κώδικα που θέλουμε να εκτελεστεί σε όλες τις περιπτώσεις, όπως για παράδειγμα να κλείσουμε ελεγχόμενα τα αρχεία του προγράμματος ή να κλείσουμε δικτυακές συνδέσεις (π.χ. συνδέσεις με βάσεις δεδομένων κ.α.). Στο παραπάνω παράδειγμα παραλλάσσεται η μέθοδος ReadFile του προηγούμενου παραδείγματος, ώστε στο //finally// block η μέθοδος κλείνει το αρχείο που άνοιξε. Η διαφορά σε σχέση με το προηγούμενο παράδειγμα είναι ότι ακόμη και εάν δημιουργηθεί ένα exception την ώρα που διαβάζουμε, η ροή του προγράμματος θα περάσει από το //finally block// και το αρχείο τελικά θα κλείσει. Αυτό δεν ισχύει στο παράδειγμα που δώσαμε προηγούμενα. +Τα αντικείμενα που θέλουμε να κλείσουν αυτόματα τα δημιουργούμε μέσα σε παρενθέσεις, αμέσως μετά το try blockΗ μεταβλητή sc έχει εμβέλεια εντός του try block και όχι έξω από αυτό. Με την ολοκλήρωση του try blockείτε συμβεί εξαίρεση, είτε δεν συμβεί, το αντικείμενο sc (τύπου Scanner) θα κλείσει αυτόματα.
- +
-Στο παραπάνω παράδειγμα δείτε την πορεία του κώδικα βγάζοντας τα σχόλια και βάζοντας σε σχόλια την γραμμή που δημιουργεί το ''IOException''. +
-<code java> +
-      while ((inputLine = in.readLine()) != null) { +
-        strDocument.append(inputLine); +
-        //throw new IOException(); +
-      } +
-</code>+
  
 |Προηγούμενο: [[:java:exceptions_intro| Εξαιρέσεις ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο: [[:java:exceptions_thrown_by_methods | Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ]]| |Προηγούμενο: [[:java:exceptions_intro| Εξαιρέσεις ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο: [[:java:exceptions_thrown_by_methods | Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ]]|
  
  
java/exceptions_try_catch_block.1489142078.txt.gz · Last modified: 2017/03/10 10:34 by gthanos