* Задължителни и незадължителни изключения
Публикувано на 19 юли 2015 в раздел ПИК3 Java.
В статията за изключения дефинирани от потребителя, а и във всички следващи, правихме изключенията като наследници на клас Exception. Това са т.нар. "checked" изключения. Ще си позволя да използвам термина като "задължителни изключения", а не да използвам буквалния превод (проверени). Щом едно изключение е задължително, то трябва:
- Методът, който го хвърля чрез throw new задължително да го упомене чрез "throws" клауза. В противен случай програмата няма да се компилира ("error: unreported exception MyException; must be caught or declared to be thrown");
- Методът, който го прихваща задължително да го обработи (да направи try-catch или да го прехвърли нататък). В противен случай програмата също няма да се компилира ("error: unreported exception MyException; must be caught or declared to be thrown").
Незадължителните изключения премахват тези ограничения - при тях не е задължително метода да указва, че ще ги хвърля и не е задължително да ги прихващате. Те се реализират чрез наследяване на клас RuntimeException. Например:
import java.util.*; import java.lang.*; import java.io.*; /* Name of the class has to be "Main" only if the class is public. */ public class MyProgram{ public static void main (String[] args){ test(0); } static void test(int i){ if(i==0) throw new MyException(); System.out.println(i); } } class MyException extends RuntimeException{ public MyException(){ super("Custom exception"); } public MyException(String msg){ super(msg); } @Override public String toString(){ return super.toString(); } }
Виждате, че метод "test" не указва "throws MyException" (а и да го направи, не сте задължени да го прихванете), а main няма try-catch блок. Въпреки това програмата ще се компилира, а при наличието на този Exception, тя ще прекъсне и ще спре своето действие (все едно main метода е хвърлил изключението).
Можем да разгледаме незадължителните изключения като свобода сами да преценяваме дали е нужно да обработваме грешката или не. Това е и причината много програмисти да ги предпочитат. Тази практика обаче не винаги е позитивна - понякога с цел да се напише по-бързо кода (спестяват се try-catch блокове) се използва RuntimeException и впоследствие програмистите забравят да обработят изключението. Така при бъдещата употреба в програмата има заложен "бъг", който я "чупи".
За да определите дали да използвате задължително или незадължително изключение, може да следвате следните правила:
- Ако гарантирате, че сами ще управлявате данните така, че изключението няма да възникне, използвайте незадължително изключение. Така кодът става по-четим и по-кратък. Например когато обхождаме масив може да възникне ArrayOutOfBoundsException, но реално ние "знаем какво правим" и сами се контролираме да не прекрачим границите на масива, вместо да обграждаме всеки наш цикъл с try-catch. Така ArrayOutOfBoundsException e незадължително изключение - всички програмисти знаят, че границите на масив не трябва да се прекрачват и съответно те не го правят, т.е. няма нужда да усложняваме кода си с catch блок, който никога няма да бъде достигнат (освен при новаците в програмирането естествено, но това е друга тема);
- Ако друг програмист трябва да извиква вашите методи и имате изключения, които са нетривиални за управление, използвайте задължителни изключения - така ще предотвратите грешка на другия човек;
- Никога не използвайте незадължителни изключения само за да си спестите време в писането на try-catch блокове. Това е един от основните източници на некачествен програмен код. Ако едно изключение трябва да бъде обработвано, направете го, а не отлагайте с времето. Тук е моментът да вметна, че една от причините в практиката да се използват много незадължителни изключения, а в академичните среди в учебните помагала напротив - почти изцяло задължителни, - е именно с цел в обучението хората да се научат винаги да обработват грешките, а не да ги "претупват";
- Изключенията, при които "няма какво да се направи", т.е. нормалната работа на програмата не може да бъде възстановена по никакъв начин, са винаги незадължителни. Подобни изключения са, че е свършила паметта, станал е проблем с виртуалната машина или операционната система и т.н. Много е вероятно никога да не видите практически случаи, в които вие сами да напишете подобно изключение.
Накрая бих споменал като добра практика винаги методите да указват всички изключения, които се хвърлят ръчно чрез throw new, дори те да са незадължителни.
Добави коментар