User Tools

Site Tools


java:exceptions_thrown_by_methods

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_thrown_by_methods [2020/02/27 20:30] gthanosjava:exceptions_thrown_by_methods [2021/03/23 07:33] (current) – external edit 127.0.0.1
Line 1: Line 1:
 ====== Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ====== ====== Χειρισμός της εξαίρεσης σε υψηλότερο επίπεδο ======
  
-Στην προηγούμενη ενότητα δείξαμε πως μπορούμε να χειριστούμε μια εξαίρεση όταν προκύπτει. Η Java μας δίνει την δυνατότητα να μην διαχειριστούμε την εξαίρεση μέσα στη μέθοδο που δημιουργείται ή σε κάποια άλλη μέθοδο η οποία βρίσκεται πιο πάνω στη σειρά των μεθόδων που έχουν ήδη κληθεί και βρίσκονται μέσα στην στοίβα εκτέλεσης του προγράμματος +Ας υποθέσουμε τώρα ότι θέλουμε να επαναλάβουμε την λειτουργικότητα του προηγούμενου προγράμματος εντός της νέας μεθόδου getRatio που καλείται από τη main, αλλά η διαχείριση της εξαίρεσης να εξακολουθεί γίνεται στη μέθοδο main.
  
-<WRAP info 80% center round+<code java ExceptionHandling.java
-Ας υποθέσουμε ότι έχετε τις μεθόδους **main**, **method1**, **method2**, **method3** όπου η ιεραρχία κλήσεων μεταξύ τους είναι η εξής: +import java.util.Scanner; 
-  * Η **main** καλεί την **method1**+import java.util.NoSuchElementException; 
-  * Η **method1** καλεί την **method2**+import java.util.InputMismatchException;
-  * Η **method2** καλεί την **method3**.+
  
-  * Εάν συμβεί ένα **Exception** μέσα στη μέθοδο **method3** τότε αυτό μπορούμε να το διαχειριστούμε είτε μέσα στην **method3**, είτε μέσα στις **method2**, **method1** και **main**.  +public class ExceptionHandling { 
-  * Αντίστοιχα, εάν συμβεί ένα **Exception** μέσα στη μέθοδο **method2** τότε αυτό μπορούμε να το διαχειριστούμε είτε μέσα στην **method2**, είτε μέσα στις **method1** και **main**+   
 +  public static double getRatio(Scanner sc) throws NoSuchElementException { 
 +    System.out.print("Width: "); 
 +    int width = sc.nextInt(); 
 +    System.out.print("Height: "); 
 +    int height = sc.nextInt(); 
 +    return width / (double)height; 
 +  
 +  public static void main(String []args) { 
 +    try (Scanner sc = new java.util.Scanner(System.in)){ 
 +      double ratio = getRatio(sc); 
 +      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."); 
 +    } 
 +  } 
 +
 +</code>
  
-Η **main** είναι η τελευταία μέθοδος στην οποία μπορεί να γίνει διαχείριση ενός exception. Εάν η διαχείριση δεν γίνει και στη main, τότε το πρόγραμμα τερματίζει εκτυπώνοντας στην κονσόλα το Exception που δημιουργήθηκε.+Στον παραπάνω κώδικα παρατηρούμε ότι η μέθοδος getRatio μπορεί να παράγει μία εξαίρεση, αλλά η διαχείριση της γίνεται από τη μέθοδο που την καλεί, δηλαδή τη μέθοδο main. Η μέθοδος getRatio δεν περιέχει try/catch block, είμαστε όμως υποχρεωμένοι να δηλώσουμε σε αυτή ότι παράγει ένα exception του τύπου [[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>+====== Stack Unwinding ======
  
-Ας ξαναδούμε το προηγούμενο παράδειγμα ελαφρά παραλλαγμένο+Κατά την πυροδότηση μίας εξαίρεσης το πρόγραμμα διακόπτεται στο σημείο που συμβαίνει η εξαίρεση και συνεχίζει την εκτέλεση του στο πρώτο catch block, το οποίο ταιριάζει με τον τύπο της εξαίρεσης. Το stack της διεργασίας αναδιπλώνεται αυτόματα μέχρι το σημείο που θα βρεθεί το κατάλληλο catch blockΚαμία από τις συναρτήσεις που εμπλέκονται δεν τερματίζει ομαλά μέχρι να φτάσουμε στο catch block. Δείτε το παρακάτω παράδειγμαστο οποίο η πιθανή εξαίρεση παράγεται μέσα στη μέθοδο readInt.
-  - Καταρχήν διαχωρίζουμε το ''FileNotFoundException'' από το ''IOException'' σε δύο διαφορετικά try blocks. +
-  - Στην συνέχεια κάνουμε comment-out τις γραμμές που ελέγχουν το ''FileNotFoundException'' και ανταυτού προσθέτουμε μία δήλωση ''throws FileNotFoundException'' στην δήλωση της μεθόδου. +
-  - Τέλος διαχειριζόμαστε την εξαίρεση μέσα στη μέθοδο ''main''.+
  
-<code java WholeFileReader.java>+<code java ExceptionHandling.java> 
 +import java.util.Scanner; 
 +import java.util.NoSuchElementException; 
 +import java.util.InputMismatchException;
  
-import java.io.*; +public class ExceptionHandling {
-import java.lang.*; +
- +
-public class WholeFileReader {+
      
-  public String readFile(String path) throws FileNotFoundException +  public static int readInt(Scanner sc) throws NoSuchElementException 
-    FileReader fReader = null;+    return sc.nextInt(); 
 +  }
      
-    try { +  public static double getRatio(Scanner scthrows NoSuchElementException 
-      File file = new File (path)+    System.out.print("Width: "); 
-      fReader = new FileReader(file); +    int width = readInt(sc); 
-      BufferedReader in = new BufferedReader(fReader); +    System.out.print("Height: "); 
-      String inputLine; +    int height readInt(sc); 
-      StringBuffer strDocument = new StringBuffer(); +    return width / (double)height;
-      try +
-        while ((inputLine = in.readLine()) != null) { +
-          strDocument.append(inputLine); +
-        } +
-         +
-      } +
-      catch(IOException ex) { +
-        System.out.println("IOException occured while reading from file "+path); +
-            +
-      return strDocument.toString(); +
-    +
-    /* //Remove exception from here. Handle it at a higher level +
-    catch(FileNotFoundException ex) { +
-      System.out.println("The specified file was not found at "+ args[0]); +
-    }*/ +
-    finally { +
-      if( fReader !null) { +
-        try { +
-          System.out.println("Closing file"); +
-          fReader.close(); +
-        }  +
-        catch(IOException ex) { +
-          System.out.println("IOException occured while closing file "+path); +
-        } +
-      } +
-    } +
-    +
   }   }
      
-  public static void main(String args[]) { +  public static void main(String []args) { 
-    WholeFileReader wfr = new WholeFileReader(); +    double ratio = -1.0; 
-    try +    try (Scanner sc = new java.util.Scanner(System.in)){ 
-      System.out.println(wfr.readFile(args[0]) );+      ratio = getRatio(sc); 
 +      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) { +  
-      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>
  
-Στον παραπάνω κώδικα βλέπουμε την περίπτωση στην οποία __δεν__ διαχειριζόμαστε την εξαίρεση εντός της μεθόδου ''readFile'' αλλά αφήνουμε να περάσει η εξαίρεση στην μέθοδο που την καλεί (στην περίπτωση μας η μέθοδος ''public static void main(String args[])''και την διαχειριζόμαστε εκεί.  +Στο παραπάνω παράδειγμαόταν θα συμβεί μία εξαίρεση στη μέθοδο readInt, ο κώδικας σταματήσει την εκτέλεση του και καμία από τις συναρτήσεις που έχουν κληθεί ενδιάμεσα (getRatio, readInt) δεν θα επιστρέψει ομαλά. Αυτό που θα συμβεί είναι ότι ο κώδικας θα συνεχίσει να εκτελείται στο κατάλληλο catch block, που βρίσκεται στη μέθοδο main. Αφού συμβεί το exception, η μεταβλητή ratio έχει την τιμή -1.0 με την οποία αρχικοποιήθηκε. 
- +
-Εφόσον δεν διαχειριζόμαστε το //Exception// στην δήλωση της μεθόδου, είναι υποχρεωτικό από τον μεταγλωττιστή της Java να προσθέσουμε την επιπλέον δήλωση  +
- +
-<code java> +
-throws FileNotFoundException +
-</code> +
- +
-όπου περιγράφεται ποια //Exceptions// μπορεί να μην  διαχειριστεί μία μέθοδος και να αφήσει τη διαχείριση τους στις μεθόδους που την καλούν. Μία μέθοδος μπορεί να μην διαχειριστεί και να αφήσει προς διαχείριση στις μεθόδους που την καλούν περισσότερα του ενός //Exceptions//.  +
- +
-Η δήλωση **throws** υποχρεώνει τον compiler να βγάλει σφάλμα εάν η "παραπάνω" μέθοδος (η μέθοδος που καλεί την εν λόγω μέθοδο) **α)** δεν διαχειρίζεται το //Exception// και **β)** δεν περιέχει με τη σειρά της μία δήλωση **throws** ώστε το //Exception// να διαχειριστεί σε ποιο πάνω επίπεδο..+
  
-|Προηγούμενο: [[:java:exceptions_try_catch_block| Διαχείριση Εξαιρέσεων ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο: [[:java:exceptions_throwing | Δημιουργία και πυροδότηση εξαίρεσης ]]|+|Προηγούμενο: [[:java:exceptions_try_catch_block| Διαχείριση Εξαιρέσεων ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο: [[:java:exceptions_throwing | Δημιουργία νέων τύπων εξαιρέσεων και πυροδότηση εξαιρέσεων ]]|
  
java/exceptions_thrown_by_methods.1582835432.txt.gz · Last modified: 2020/02/27 20:30 by gthanos