Η γλώσσα προγραμματισμού Java χρησιμοποιεί τις εξαιρέσεις για να χειρίζεται σφάλματα και άλλα έκτακτα συμβάντα.
Μια εξαίρεση είναι ένα γεγονός που συμβαίνει κατά την εκτέλεση ενός προγράμματος και διαταράσσει την κανονική ροή των εντολών. Στη Java οι εξαιρέσεις πετιούνται ρητά, και η ενέργεια του να πετάς μια εξαίρεση ονομάζεται πέταγμα εξαίρεσης. Η ενέργεια του να χειρίζεσαι μια εξαίρεση ονομάζεται σύλληψη εξαίρεσης.
Στη Java, όλες οι εξαιρέσεις είναι υποκλάσεις της κλάσης Exception, η οποία είναι και η ίδια υποκλάση της Throwable.
Η Java διακρίνει δύο τύπους εξαιρέσεων:
Οι ελεγχόμενες εξαιρέσεις είναι έκτακτες συνθήκες που μια εφαρμογή πρέπει να προβλέψει και να ανακάμψει από αυτές.
Ένα παράδειγμα ελεγχόμενης εξαίρεσης είναι η FileNotFoundException, η οποία συμβαίνει όταν μια μέθοδος προσπαθεί να διαβάσει ένα αρχείο που δεν υπάρχει.
Αυτός ο τύπος εξαίρεσης ελέγχεται σε χρόνο μεταγλώττισης: οι μέθοδοι που πετούν ελεγχόμενες εξαιρέσεις πρέπει να το δηλώνουν στην υπογραφή της μεθόδου τους, και ο κώδικας που καλεί μια μέθοδο που μπορεί να πετάξει μια ελεγχόμενη εξαίρεση οφείλει να τη χειριστεί, αλλιώς ο κώδικας δεν θα μεταγλωττιστεί.
Όλες οι ελεγχόμενες εξαιρέσεις είναι υποκλάσεις της Exception που δεν επεκτείνουν την RuntimeException.
Οι μη ελεγχόμενες εξαιρέσεις είναι έκτακτες συνθήκες που μια εφαρμογή συνήθως δεν μπορεί να προβλέψει ούτε να ανακάμψει από αυτές.
Ένα παράδειγμα μη ελεγχόμενης εξαίρεσης είναι η NullPointerException, η οποία συμβαίνει όταν μια μέθοδος που περιμένει μια τιμή που δεν είναι null λαμβάνει null.
Αυτός ο τύπος εξαίρεσης δεν ελέγχεται σε χρόνο μεταγλώττισης: οι μέθοδοι που πετούν μη ελεγχόμενες εξαιρέσεις δεν είναι υποχρεωμένες να το δηλώνουν στην υπογραφή της μεθόδου τους, και ο κώδικας που καλεί μια μέθοδο που μπορεί να πετάξει μια μη ελεγχόμενη εξαίρεση δεν είναι υποχρεωμένος να τη χειριστεί.
Όλες οι μη ελεγχόμενες εξαιρέσεις κληρονομούν από την RuntimeException, η οποία είναι και η ίδια επέκταση της Exception.
Μια μέθοδος στη Java μπορεί να πετάξει μια εξαίρεση χρησιμοποιώντας την εντολή throw.
Όταν πετάς μια ελεγχόμενη εξαίρεση από μια μέθοδο, απαιτείται να το δηλώσεις στην υπογραφή της μεθόδου χρησιμοποιώντας τη λέξη-κλειδί throws, όπως φαίνεται στο παρακάτω παράδειγμα.
Αυτό αναγκάζει τον κώδικα που καλεί να προβλέψει ότι μπορεί να πεταχτεί μια εξαίρεση και να τη χειριστεί ανάλογα.
public class InsufficientBalanceException extends Exception {
}
public class BankAccount {
public void withdraw(double amount) throws InsufficientBalanceException {
if (balance < amount) {
throw new InsufficientBalanceException();
}
// rest of the method implementation
}
}
Όταν πετάς μια μη ελεγχόμενη εξαίρεση από μια μέθοδο, δεν απαιτείται να το δηλώσεις στην υπογραφή της μεθόδου, αν και υποστηρίζεται.
public class BankAccount {
public void withdraw(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Cannot withdraw a negative amount");
}
// rest of the method implementation
}
}
Ο χειρισμός των εξαιρέσεων στη Java γίνεται με τις λέξεις-κλειδιά try, catch και finally.
try.try ακολουθείται από ένα ή περισσότερα μπλοκ catch που πιάνουν τις εξαιρέσεις που πετάγονται μέσα στο μπλοκ try.catch ακολουθούνται προαιρετικά από ένα μπλοκ finally που εκτελείται πάντα μετά το μπλοκ try, ανεξάρτητα από το αν πετάχτηκε κάποια εξαίρεση ή όχι.Το παρακάτω παράδειγμα δείχνει πώς λειτουργούν αυτές οι λέξεις-κλειδιά:
public class ATM {
public void withdraw(BankAccount bankAccount, double amount) {
try {
System.out.println("Withdrawing " + amount);
bankAccount.withdraw(amount);
System.out.println("Withdrawal succeeded");
} catch (InsufficientBalanceException) {
System.out.println("Withdrawal failed: insufficient balance");
} catch (RuntimeException e) {
System.out.println("Withdrawal failed: " + e.getMessage());
} finally {
System.out.println("Current balance: " + bankAccount.getBalance());
}
}
}
Σε αυτό το παράδειγμα, όταν δεν πετάγεται καμία εξαίρεση, εκτυπώνεται το εξής:
Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0
Ωστόσο, αν η εντολή bankAccount.withdraw(amount) πετάξει μια InsufficientBalanceException, εκτυπώνεται το εξής:
Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0
Ή, σε περίπτωση που η bankAccount.withdraw(amount) πετάξει μια μη ελεγχόμενη εξαίρεση, εκτυπώνεται το εξής:
Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0
Η Java έχει επίσης μια ξεχωριστή κατηγορία που ονομάζεται Σφάλματα, τα οποία είναι σοβαρά προβλήματα εξωτερικά ως προς μια εφαρμογή.
Ένα παράδειγμα σφάλματος είναι το OutOfMemoryError, το οποίο συμβαίνει όταν μια εφαρμογή προσπαθεί να χρησιμοποιήσει περισσότερη μνήμη από αυτή που είναι διαθέσιμη στο σύστημα.
Όπως οι μη ελεγχόμενες εξαιρέσεις, έτσι και τα σφάλματα δεν ελέγχονται σε χρόνο μεταγλώττισης. Η διαφορά είναι ότι αντιπροσωπεύουν προβλήματα σε επίπεδο συστήματος και συνήθως πετιούνται από την εικονική μηχανή Java ή από το περιβάλλον και όχι από την εφαρμογή. Οι εφαρμογές γενικά δεν θα πρέπει να προσπαθούν να τα πιάσουν ή να τα χειριστούν.
Όλα τα σφάλματα στη Java κληρονομούν από την κλάση Error.
Σε αυτή την άσκηση θα φτιάξεις τον χειρισμό σφαλμάτων για μια απλή αριθμομηχανή ακεραίων. Για να μην περιπλέκουμε τα πράγματα, σου δίνονται έτοιμες μέθοδοι για την πρόσθεση, τον πολλαπλασιασμό και τη διαίρεση.
Στόχος είναι να έχεις μια αριθμομηχανή που δουλεύει και επιστρέφει μια συμβολοσειρά με το εξής μοτίβο: 16 + 51 = 67, όταν της δίνεις τα ορίσματα 16, 51 και +.
CalculatorConundrum calculator = new CalculatorConundrum();
calculator.calculate(16, 51, "+");
// => returns "16 + 51 = 67"
calculator.calculate(32, 6, "*");
// => returns "32 * 6 = 192"
calculator.calculate(512, 4, "/");
// => returns "512 / 4 = 128"
Η κύρια μέθοδος που θα υλοποιήσεις σε αυτή την εργασία είναι η CalculatorConundrum.calculate().
Δέχεται τρία ορίσματα.
Τα δύο πρώτα ορίσματα, operand1 και operand2, είναι ακέραιοι αριθμοί πάνω στους οποίους θα γίνει μια πράξη.
Το τρίτο όρισμα, operation, είναι τύπου String και σε αυτή την άσκηση χρειάζεται να υλοποιήσεις τις εξής πράξεις:
+
*
/
Ενημέρωσε τη μέθοδο CalculatorConundrum.calculate() ώστε να χειρίζεται τις μη έγκυρες πράξεις:
operation είναι null, πρέπει να πεταχτεί μια IllegalArgumentException με μήνυμα Operation cannot be null.operation είναι "", πρέπει να πεταχτεί μια IllegalArgumentException με μήνυμα Operation cannot be empty.operation είναι κάποια άλλη πράξη εκτός από +, * ή /, πρέπει να πεταχτεί μια IllegalOperationException με μήνυμα Operation '{operation}' does not exist.calculator.calculate(10, 1, null);
// => throws IllegalArgumentException with message "Operation cannot be null"
calculator.calculate(10, 1, "");
// => throws IllegalArgumentException with message "Operation cannot be empty"
calculator.calculate(10, 1, "-");
// => throws IllegalOperationException with message "Operation '-' does not exist"
Στην Java, αν προσπαθήσεις να διαιρέσεις με το μηδέν, πετιέται μια ArithmeticException.
Ενημέρωσε τη μέθοδο CalculatorConundrum.calculate() ώστε να πιάνει αυτή την εξαίρεση και μετά να πετάει μια IllegalOperationException με μήνυμα Division by zero is not allowed και αιτία την ArithmeticException που έπιασε.
calculator.calculate(512, 0, "/");
// => throws IllegalOperationException with message "Division by zero is not allowed"
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Java με 26 έννοιες158 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.