* Хвърляне на изключения
Публикувано на 24 септември 2009 в раздел ПИК3 Java.
Понякога е удачно да пишем методи, които вместо да обработват сами изключенията на операторите вътре в тях, да прехвърлят изключенията на извикващите ги методи. Това е нещо като "прехвърляне на отговорността". Такава функционалност се получава чрез оператора "throw". Ето един тривиален пример - метод, който отпечатва съдържанието на файл на екрана:
public static void showFileContents(String filename)
throws java.io.FileNotFoundException, java.io.IOException {
java.io.BufferedReader in =
new java.io.BufferedReader(
new java.io.FileReader(filename));
int readbyte;
while ((readbyte = in.read()) != -1) {
System.out.print((char)readbyte);
}
in.close();
}
public static void main(String[] args) {
try{
showFileContents("input.txt");
}
catch (java.io.FileNotFoundException e){
System.err.println("File not found");
}
catch (java.io.IOException e){
System.err.println("IO error has occured");
}
}
Виждате, че в метод showFileContents ние никъде не се погрижихме за търсене на изключения. Ако методите използвани от BufferedReader достигнат до FileNotFoundException или IOException - те просто ги прехвърлят към метода main.
Изключенията обаче могат да бъдат прехвърляни и през няколко нива. Например:
public static java.io.BufferedReader openFile(String filename)
throws java.io.FileNotFoundException, java.io.IOException{
java.io.BufferedReader in =
new java.io.BufferedReader(
new java.io.FileReader(filename));
return in;
}
public static void showFileContents(String filename)
throws java.io.IOException {
java.io.BufferedReader in = null;
try{
in = openFile(filename);
int readbyte;
while ((readbyte = in.read()) != -1) {
System.out.print((char)readbyte);
}
}
catch(java.io.FileNotFoundException e){
System.err.println("File Not Found");
}
finally{
try{
if (in!=null) in.close();
}
catch (java.io.IOException e){}
}
}
public static void main(String[] args) {
try{
showFileContents("input.txt");
}
catch (java.io.IOException e){
System.err.println("IO error has occured");
}
}
От този пример виждаме, че ако в метод openFile възникне някаква грешка с отварянето на файл, то тя ще бъде прехвърлена към извикващия метод - showFileContents. Той от своя страна се грижи за обработката на FileNotFoundException, но не и за IOException. Така ако се получи IOЕxception (независимо дали в метод openFile или showFileContents) тя ще бъде хвърлена към метода main, който вече е длъжен да я обработи. Така получихме т.нар. "каскадно" обработване на грешка.
Предвидена е и още една възможност - самите ние да "хвърлим" изключение към викащия метод. Нека напишем метод, който получава като аргумент масив и число и дели всички елементи на масива на това число. При подадено число 0, то методът ще хвърли ArithmeticException:
public static void divArray(int[] arr, int divisor)
throws java.lang.ArithmeticException{
if (divisor == 0) throw new java.lang.ArithmeticException("You divide by 0");
for (int i=0; i<arr.length; i++){
arr[i] /= divisor;
}
}
public static void main(String[] args) {
int[] arr = {1,3,6,0,9};
try{
divArray(arr, 0);
}
catch (java.lang.ArithmeticException e){
System.err.println(e.getMessage());
System.err.println("We will only print the original array:");
}
for (int i: arr){
System.out.print(i+" ");
}
}
Специално сме удебелили една важна функционалност - методът "getMessage()". Виждате, че при създаването на изключението ние подадохме като параметър текст "You divide by 0". Когато прихващаме това изключение в метода main, то чрез методът "getMessage()" ние взимаме именно този текст и в случая го отпечатваме в стандартния поток за грешки. Изключенията имат такъв текст и по подразбиране, но по този начин е ясно, че можем да сме по-гъвкави.
След като знаем за тази функционалност, нека се върнем към "лошия пример" от предишна статия и да покажем как можем да я използваме:
// Izchisliava x ot a.x + b = 0
double a = 0;
double b = 4;
try{
if (a == 0){
if (b == 0) throw new java.lang.ArithmeticException("Vsiako x e reshenie");
else throw new java.lang.ArithmeticException("Niama reshenie");
}
System.out.println("x = "+(-b/a));
}
catch (java.lang.ArithmeticException e){
System.out.println(e.getMessage());
}
Естествено пак ще повторим казаното в предишната статия, че работата с изключения трябва максимално да се отбягва. Подобни примери могат да доведат само до загуба на производителност и нищо полезно. Затова използвайте и хвърляйте изключения само когато е необходимо! С този пример просто демонстрираме възможностите на throw и нищо друго.
Добави коментар