Sunteți pe pagina 1din 4

Lucrarea nr.

1. Tratarea excepţiilor.

Scopul lucrării

Lucrarea de faţă are ca scop prezentarea mecanismului de tratare a excepţiilor, cu ajutorul


căruia se pot scrie aplicaţii robuste. Se vor prezenta aspectele teoretice iar pentru exemplificare se va
utiliza terminologia specifică limbajului Java.

1.1. Excepţii

1.1.1. Ce sunt excepţiile?

Pe parcursul execuţiei unui program pot să apară situaţii în care unele operaţii nu se pot
efectua (spre exemplu nu se poate deschide un fişier deoarece acesta nu există). Pentru determinarea
acestor situaţii în programarea clasică se efectuau o serie de teste: se testa valoarea întoarsă de o funcţie
despre care se ştie că poate să eşueze şi/sau se verifica valoarea unor indicatori de eroare globali. Acest
stil de programare, pe lângă faptul că este greu de urmărit, prezintă câteva neajunsuri majore: nu
tratează situaţiile neprevăzute şi necesită un efort de programare mare pentru tratarea unor cazuri rar
întâlnite. Secvenţa de pseudocod de mai jos ilustrează stilul de programare clasic:

int status = apelezCevaCareFuncţioneazăAproapeÎntotdeauna( );


if ( status == VALOARE_ANORMALĂ ) {
… // s-a întâmplat ceva neprevăzut, se impune tratarea problemei
switch( unIndicatorDeEroareGlobal ) {
… // tratarea specifică a problemelor
}
} else {
… // totul e OK, execuţia continuă normal
}

Limbajele de programare mai noi introduc noţiunea de excepţie ca fiind o situaţie neprevăzută
(spre exemplu împărţirea la zero). Un programator în limbajul Java se poate întâlni cu trei categorii de
excepţii [5]:
 excepţii normale;
 excepţii de execuţie (run-time);
 erori.
Excepţii normale sunt cauzate de o anumită secvenţă de cod. Se poate spune cu alte cuvinte că
locul de apariţie al excepţiei este previzibil, chiar dacă excepţia în sine nu e. Un exemplu în acest sens
ar fi o excepţie FileNotFoundException, care apare ca urmare a unei încercări de a deschide un fişier
inexistent. Un alt exemplu ar fi depăşirea indicilor unui tablou într-o expresie care utilizează tabloul.
Spre deosebire de prima categorie, cauza excepţiilor run-time este mai greu de stabilit. Să
considerăm exemplul unei excepţii NullPointerException, care poate să apară la oricare referire a unei
instanţe nule, sau ArithmeticException, care poate să apară în orice expresie matematică ce conţine o
împărţire la zero.
Erorile semnalează evenimente de genul depăşirii stivei sau a adresării în afara memoriei
fizice şi semnalează funcţionarea defectuoasă a maşinii virtuale sau probleme legate de sistemul de
operare (spre exemplu: OutOfMemoryError, StackOverflowError); tratarea acestora de către
programator nu prezintă interes practic.
Mecanismul de tratare a erorilor prezintă câteva avantaje faţă de metodele tradiţionale [5]:
 permite separarea codului responsabil de funcţionalitatea programului de tratarea erorilor,
mărind astfel lizibilitatea;
 oferă un mecanism ce permite propagarea erorilor în stiva de apeluri; astfel o metodă
apelantă poate să trateze o eroare ce survine într-una dintre metodele apelate;
 permite diferenţierea şi tratarea mai multor tipuri de condiţii anormale.
1.1.2. Cuvintele cheie try, throw, catch

Programatorul poate delimita o secvenţă care ar putea genera o excepţie cu ajutorul cuvintelor
rezervate try şi catch. Să considerăm un prim exemplu:

int x, y;

try {
y = 1/x;
/** x ar putea fi nul */
} catch (Exception e) {
System.out.println(e);
y = 0;
}
System.out.println(“y = “ + y);

try se foloseşte pentru a delimita un bloc de instrucţiuni suspect de a genera o excepţie. După
acolada ce închide blocul se observă folosirea lui catch pentru “prinderea” eventualelor excepţii.
În cazul în care valoarea lui x este diferită de 0, împărţirea poate fi efectuată şi execuţia
programului continuă cu afişarea valorii lui y. Dacă x ia valoarea zero atunci împărţirea nu se poate
efectua şi se va genera o excepţie. În exemplul de mai sus s-a prins o excepţie generală de tip
Exception, care va fi afişată. Tratarea erorii constă în iniţializarea y cu valoarea zero.

1.1.3. Excepţii multiple

Într-un bloc try pot să se genereze mai multe tipuri de excepţii, care necesită tratare
diferenţiată. Pentru aceasta se pot folosi mai multe blocuri catch, fiecare pentru un caz particular.
Secvenţa de mai jos ilustrează un astfel de exemplu:

/** Incercaţi şi valori diferite de zero */


final int N = 0;
Integer unInt = new Integer(N);

/** comentaţi următorul rând de program */


unInt = null;

try {
y = 1 / unInt.intValue();
/** x ar putea fi nul */
} catch (ArithmeticException a) {
/** Impărţire la 0 */
System.out.println(a);
y = 0;
} catch (NullPointerException n) {
/** folosirea unei referinţe nule */
System.out.println(n);
} catch (Exception e) {
/** Altceva... */
System.out.println(e);
}
System.out.println("y=" + y);

Se pot specifica mai multe tipuri de excepţii, dintre care se va alege primul care este
compatibil cu excepţia curentă. Datorită faptului că excepţiile sunt la rândul lor obiecte, derivate direct
sau indirect din java.lang.Error şi java.lang.Exception (derivate la rândul lor din java.lang.Throwable),
observaţiile referitoare la atribuirea extinsă la subclase (vezi Error: Reference source not found) sunt
valabile. Consecinţa este că se prind mai întâi excepţiile specializate şi mai apoi excepţiile generale.

Excepţiile se “aruncă” cu ajutorul lui throw. Exemplul de mai jos va arunca o excepţie dacă
valoarea lui i este negativă:


if (i < 0) {
throw new Exception( "Număr negativ" );
}

1.1.4. Clauza throws. Rearuncarea excepţiilor

Limbajul Java a fost proiectat în vederea dezvoltării de programe cât mai robuste. De aceea se
cere ca orice metodă care ar putea arunca o excepţie normală fie să o trateze cu un bloc try…catch, fie
să o declare cu o clauză throws:

public void metodaExceptionala( ) throws Exception {…}

…{
try {
metodaExceptionala( ) ;
} catch (Exception e) {…}
}

O metodă declarată ca mai sus trebuie neapărat inclusă într-un bloc try…catch, altfel se va
genera o eroare de compilare. Prin această restricţie impusă de limbaj se forţează conştientizarea
excepţiilor care ar putea să apară, deci adoptarea unui stil de programare defensiv. Se recomandă ca
metodele “periculoase” să fie declarate cu clauza throws.

try {
/** Se aşteaptă 1000 milisecunde, timp în care
firul curent de execuţie poate fi întrerupt */
Thread.sleep(1000)
} catch (InterruptedException e) {…}

Excepţiile de execuţie (descendente ale clasei RuntimeException) precum şi erorile sunt


considerate excepţii implicite datorită faptului că pot să apară practic oriunde în program. Din această
cauză nu e obligatorie declararea şi tratarea explicită. Câteva exemple de excepţii implicite sunt:
NullPointerException, ArithmeticException, IllegalArgumentException sau VirtualMachineError.
Prin folosirea lui throws se poate evita tratea unei excepţii loco şi se poate delega
responsabilitatea uneia dintre metodele apelante. Excepţia va fi tratată de primul bloc try care prinde o
excepţie compatibilă cu cea curentă.
throw poate fi folosit la “re-aruncarea” unei excepţii deja tratate, forţându-se astfel tratarea
acesteia şi în blocurile try exterioare:

try{

try {
} catch (Exception e) {
/** tratez şi aici… */
throw e;
}
} catch (Exception e) {
/** … şi aici */

}

1.1.5. Clauza finally

Excepţiile pot să apară în timpul unor operaţii care necesită alocare de resurse (ex: deschidere
de fişiere). Pentru a da posibilitatea terminării “curate”, cu dezalocarea tuturor resurselor, limbajul Java
prevede clauza finally.
Codul aferent unei clauze finally va fi executat întotdeauna, indiferent de modul de părăsire a
blocului try:
 normal, prin execuţia fără “evenimente” şi atingerea sfârşitului blocului try;
 datorită unui break, continue sau return;
 datorită unei excepţii tratate prin catch;
 datorită unei excepţii netratate prin catch.
try {

} catch (Exceptia1) {

} catch (Exceptia2) {

} finally {
System.out.println("De mine nu scapi!");
}

1.2. Tema practică


 Modificaţi primul exemplu din această lucrare astfel încât variabilele x, y să fie de tip
double. Explicaţi ce se întâmplă.
 Modificaţi ordinea excepţiilor prinse în exemplul al doilea astfel: Exception,
NullPointerException, ArithmeticException. Explicaţi ce se întâmplă.

S-ar putea să vă placă și