User Tools

Site Tools


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 [2021/03/22 15:44] – [Παράδειγμα] gthanosjava:exceptions_try_catch_block [2021/03/23 07:29] (current) – [Try with resources block] gthanos
Line 67: Line 67:
  
 <WRAP tip 80% center round> <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]].+Η σειρά διαχείρισης των εξαιρέσεων έχει σημασία. Εφόσον, δημιουργηθεί μία εξαίρεση, το 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]].
  
-Εάν επιχειρήσετε να αντιμεταθέσετε τα δύο catch blocks αυτό που θα συμβεί είναι να λάβετε ένα μήνυμα λάθους από τον μεταγλωττιστή. Ο λόγος είναι ότι επειδή η κλάση InputMismatchException είναι υποκλάση της NoSuchElementException, η αντιστροφή των catch block συνεπάγεται ότι ακόμη και εάν συμβεί μία εξαίρεση του τύπου InputMismatchException, το σχετικό catch block δεν θα κληθεί ποτέ. Ο λόγος είναι ότι το πρώτο catch block για τη διαχείριση των εξαιρέσεων του τύπου NoSuchElementException θα διαχειριστεί και τις εξαιρέσεις του υπο-τύπου InputMismatchException.+Εάν επιχειρήσετε να αντιμεταθέσετε τα δύο 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> </WRAP>
  
-==== Παράδειγμα 2ο - Ανοίγοντας ένα αρχείο για διάβασμα ==== 
  
-Παρακάτω δίνεται ένα πιο σύνθετο παράδειγμα μία μεθόδου που διαβάζει ένα αρχείο κειμένου και το επιστρέφει στη μορφή ενός String.+===== Finaly Block =====
  
-<code java WholeFileReader.java+Στον παραπάνω κώδικα, εμφανίζεται η κλήση της μεθόδου [[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]].
-import java.io.*; +
-import java.lang.*;+
  
-public class WholeFileReader { +Η κλήση της μεθόδου όμως συμβαίνει μόνο εάν δεν παραχθεί εξαίρεση. Στην περίπτωση που παραχθεί, το αντικείμενο θα παραμείνει ενεργό, πράγμα που σε ένα μεγαλύτερο πρόγραμμα δεν θα ήταν επιθυμητό (στο παρόν πρόγραμμα, το αντικείμενο θα κλείσει αμέσως μετά με την ολοκλήρωση του προγράμματος). Για το σκοπό αυτό εισάγεται η έννοια του finally block, ως ένα block που έπεται των catch blocks και σκοπό έχει να εκτελεστεί σε όλες τις περιπτώσεις, δηλαδή: 
-   +  * Εάν προκύψει η εξαίρεση που έχουμε φροντίσει να διαχειριστούμε (στο παρακάτω παράδειγμα //FileNotFoundException//)
-  public String readFile(String path{+  * Εάν προκύψει μια εξαίρεση ενός τύπου που δεν έχουμε φροντίσει να διαχειριστούμε, εντός των υφιστάμενων catch blocks. 
 +  * Εάν δεν προκύψει καμία απολύτως εξαίρεση. 
 + 
 +Δείτε το προηγούμενο παράδειγμα, αλλαγμένο ώστε να ενσωματώνει ένα **finally** block. Στο παρακάτω πρόγραμμα το αντικείμενο sc θα κλείσει είτε συμβεί εξαίρεση, είτε όχι.
  
-    try { +<code java ExceptionHandling.java> 
-      /* open file for reading..+import java.util.Scanner
-       */ +import java.util.NoSuchElementException
-      File file = new File (path); +import java.util.InputMismatchException
-      FileReader fReader = new FileReader(file); + 
-      BufferedReader in = new BufferedReader(fReader); +public class ExceptionHandling {
-      String inputLine; +
-      StringBuffer strDocument = new StringBuffer(); +
-      /* read file line by line +
-       */ +
-      while ((inputLine = in.readLine()) != null) { +
-        strDocument.append(inputLine)+
-        //throw new IOException(); +
-      } +
-      System.out.println("Closing File!")+
-      /* close file and return str..+
-       */ +
-      fReader.close()+
-      return strDocument.toString(); +
-    } +
-    /* If file was not found... +
-     */ +
-    catch(FileNotFoundException ex) { +
-      System.out.println("The specified file was not found at "+ path); +
-      return ""; +
-    } +
-    /* If an I/O related exception occures... +
-     */ +
-    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/FileNotFoundException.html|FileNotFoundException]] objects, ενώ το δεύτερο catch block αφορά [[http://docs.oracle.com/javase/7/docs/api/java/io/IOException.html|ΙΟException]] 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.1616427880.txt.gz · Last modified: 2021/03/22 15:44 by gthanos