Sunteți pe pagina 1din 11

smaranda.belciug@inf.ucv.

ro Laborator 4 Cazuri de excepie: tratarea erorilor n programele reale, erorile apar din una din urmtoarele cazuri: Programatorul nu a anticipat toate situaiile n care ar putea ajunge programul (sau nu a avut timpul necesar pentru a-l testa suficient) Date eronate primite de la utilizatori Fiiere care nu mai conin date corecte Conexiuni de reea care nu mai funcioneaz Dispozitive hardware care nu mai rspund Explozii solare.. monstrulei.. etc n Java aceste evenimente ciudate se numesc excepii. Excepiile, tratate prin metoda veche i confuz n majoritatea limbajelor de programare, tratarea erorilor presupune mult munc, crearea de structuri complexe similare ca funcionare cu blocurile de instruciuni if.. else sau switch din Java. Exemplu. Incrcarea unui fiier poate crea destule probleme din cauza numrului mare de erori ce pot aprea: erori pe disc, negsirea fiierului etc. int stare = incarcaFisier(); if (stare != 1){ //s-a intamplat ceva neobisnuit, trebuie s raportm switch (stare) { case 2: //fisier negasit case 3: //eroare pe disc case 4: //fisier corupt case 5: //alta eroare } }else { // fisierul s-a incarcat corect, se continua programul } Chiar dac exemplul anterior folosete sintaxa Java, nu va trebui s folosii aceast tehnic n programele dumneavoastr. Limbajul introduce o modalitate mai bun de tratare a situaiilor de excepie (erorilor): prin folosirea unui grup de clase denumite excepii.

smaranda.belciug@inf.ucv.ro Excepii n Java Atunci cnd programul se termin brusc este din cauz c a fost semnalat o excepie (thrown aruncat). Excepiile pot fi semnalate de sistem sau, explicit, de programul pe care l-ai scris. Excepiile pot fi i interceptate (caught). Interceptarea unei excepii presupune tratarea situaiilor speciale pentru ca programul dumneavoastr s nu se mai blocheze. Excepiile Java sunt, de fapt, obiecte, instane ale unor clase care motenesc clasa Throwable. O instan a clasei Throwable este creat atunci cnd se semnaleaz o excepie. Clasa Throwable are dou subclase: Error i Exception. Instanele clasei Error reprezint erori interne ale mediului de lucru Java (maina virtual). Aceste erori sunt rare i de obiecei fatale; nu putei face mare lucru cu ele (nici s le interceptai i nici s le semnalai), ns exist pentru ca Java s le poate folosi dac are nevoie de ele. Clasa Exception este mai interesant. Subclasele Exception se mpart n dou grupuri: Excepii de execuie (runtime), care sunt subclase ale clasei RuntimeException, cum ar fi ArrayIndexOutofBounds, SecurityException sau NullPointerException; Alte excepii, cum ar fi EOFException sau MalformedURLException Excepiile de execuie (runtime) apar, de obicei, deoarece codul nu este bine proiectat. De exemplu, excepia ArrayIndexOutofBounds nu ar trebui sa fie niciodat semnalat dac ai verificat c nu depii limitele unui tablou. Excepia NullPointerException nu ar trebui s apar dect dac ncercai s folosii o variabil nainte de a o configura s memoreze un obiect. Ultimul grup de excepii este cel mai interesant deoarece aceste excepii avertizeaz c se ntmpl ceva ciudat i care nu poate fi controlat. De exemplu, excepia EOFException apare atunci cnd ncercai s citii dintr-un fiier i acesta se termin mai nainte de v ateptai. Excepia MalformedURLException apare atunci cnd adresa URL nu este n formatul corespunztor. Gestionarea excepiilor Cu ct lucrai mai mult cu biblioteci Java, cu att mai mult crete posibilitatea de a ntlni o excepie de compilare.

smaranda.belciug@inf.ucv.ro Protejarea codului i interceptarea erorilor S presupunem c ai scris un cod i c la un test de compilare ai obinut un mesaj de excepie. n funcie de mesaj, fie interceptai eroarea, fie declarai c metod o poate semnala. Pentru a intercepta o excepie trebuie realizate dou lucruri: Protejai codul care conine metoda ce poate semnala excepia n cadrul unui bloc try Testai i tratai excepia n cadrul unui bloc catch Operaiunile try (ncearc) i catch (intercepteaz) nseamn, de fapt, ncearc aceast poriune de cod, care poate cauza o excepie. Dac se execut cu succes, continu programul. Dac nu, intercepteaz excepia si trateaz-o. Partea din interiorul instruciunii catch este similar listei de argumente a unei metode. Ea conine clasa a crei excepie a fost interceptat i un nume de de variabli (de obicei se folosete e). Astfel, n cadrul blocului putei s v referii la obiectul de excepie interceptat. O folosire uzual a acestui obiect este apelarea metodei getMessage(). Aceast metod este prezent n toate excepiile i afieaz un mesaj detaliat referitor la ceea ce s-a ntmplat. try{ Thread.sleep(1000); }catch (InterruptedException e){ System.out.println(Eroare: +e.getMessage()); } Exemplu 1. Citirea unui fiier de pe disc. try{ while (nrOcteti <= unBuffer.length){ unFluxIntrare.read(unBuffer); nrOcteti++; } } catch (IOException e){ System.out.println(Hopa! O exceptie IOException am citit doar + nrOcteti); //cod de reinitializare } Exemplu 2. try{ //cod care poate genera exceptii }catch (IOException e1){

smaranda.belciug@inf.ucv.ro //se trateaza exceptiile de intrare/iesire }catch (ClassNotFoundException e2){ // se trateaza exceptiile de inexistenta a clasei }catch (InterruptedException e3){ //se trateaza exceptiile de intrerupere } ntr-un bloc catch multiplu, primul bloc care va corespunde exceptiei va fi executat, iar celelalte ignorate. Clauza finally S presupunem c n codul dvs. exist o anumit aciune care trebuie neaprat executat, indiferent ce se ntmpl, indiferent dac excepia este semnalat sau nu. Pentru realizarea acestui lucru se pot introduce aceste aciuni n cadrul unui bloc catch, ct i n afara sa, dar aceasta nseamn o duplicare a codului n dou locuri diferite. n loc s procedai astfel, introducei o copie a codului ntr-o poriune special a blocului try.. catch, denumit finally. try{ citesteFisierText(); }catch(IOException e){ //tratati erorile de intrare/iesire }finally{ inchideFisierText(); }

class Final{ int[] num1 = {12,15,10,8,-1,7}; int[] num2 = {1,5,20,8,1,13}; public static void main(String[] args){ Final fin = new Final(); System.out.println("Primul tablou: "); fin.citesteNumere(fin.num1); System.out.println("Al doilea tablou: "); fin.citesteNumere(fin.num2); } void citesteNumere(int[] tablouNum){ int index = 0; int ultimulNr = 0; try{ while(index < tablouNum.length){ ultimulNr = tablouNum[index++]; if (ultimulNr == -1) return; } }finally{ System.out.println("Ultimul numar citit: " + ultimulNr); }

smaranda.belciug@inf.ucv.ro
return; } }

Declararea metodelor care pot semnala excepii Pentru a indica faptul c o metod poate semnala o excepie, vei folosi n definiia sa o clauz speciala, denumit throws. Clauza throws Pentru a indica faptul c o poriune a unei metode poate semnala o excepie, este suficient s adugai cuvntul cheie throws dup semntura metodei, i s specificai numele excepiilor pe care le poate semnala metoda dvs: public boolean metodaMea(int x, int y) throws oExceptie{ // } Dac metoda dvs. poate semnala mai multe tipuri de excepii, puteti s le specificai pe toate n clauza throws, separate prin virgule: public boolean oAltaMetodaaMea(int x, int y) throws oExceptie, oADouaExceptie, oATreiaExceptie { // } De reinut. Specificarea clauzei throws n definiia metodei dvs. nu nseamn dect c metoda poate semnala o excepie dac ceva merge prost, nu i c va face acest lucru. Clauza throws ofer doar o informaie suplimentar referitoare la potenialele excepii i permite compilatorului Java s se asigure c metoda este corect folosit de utilizatori. Trasmiterea excepiilor n afar de declararea metodelor care semnaleaz excepii, exist i un alt caz n care definiia metodei dvs poate conine o clauza throws. n aceast situaie, dorii s folosii o metod care semnaleaz o excepie, dar nu dorii s interceptai sau s tratai excepia respectiv. Exemplu. Citirea din fiier. public void citesteFisier(String numeFisier) throws IOException{ //aici se deschide fisierul si se initializeaza fluxul while (nrOcteti <= unBuffer.length){ unFluxIntrare.read(unBuffer); nrOcteti++;

smaranda.belciug@inf.ucv.ro } } Clauza throws i motenirea Dac definiia metodei dvs suprascrie o metod din superclas care conine o clauz throws, exist reguli speciale prin care se specific modul cum trateaz metoda suprascris clauza throws. Spre deosebire de alte pri ale semnturii metodei, care trebuie s le imite pe cele ale metodei suprascris, noua metod nu necesit acelai set de excepii stabilit n cadrul clauzei throws. Metoda dvs. poate semnala mai puine tipuri de exceptii. public class RedareRadio{ public void startRedare() throws ExceptieSunet { // } } public class RedareStereo extends RedareRadio{ public void startRedare(){ //. } } Reciproca acestei reguli nu este adevrat: o metod a unei subclase nu poate semnala mai multe excepii (chiar dac acestea sunt de tipuri diferite sau aparin unor clase de excepii mai generice) dect metoda superclasei sale. Crearea i semnalarea propriilor excepii Semnalarea excepiilor Pentru a semnala o excepie, trebuie s creai mai nti o instan a sa. O dat obinut aceast instan, putei folosi instruciunea throw pentru a o semnala. NotInServiceException() nis = new NotInServiceException(); throw nis; n funcie de clasa de excepie pe care o folosii, aceasta poate dispune n constructorul su de mai multe argumente pe care le putei utiliza. Cel mai des ntlnit dintre acestea este un argument ir, care v permite s descriei problema mai detaliat (lucru foarte folositor n depanare). NotInServiceException() nis = new NotInServiceException(Exceptie: Baza de date nu este activa); throw this;

smaranda.belciug@inf.ucv.ro Crearea propriilor excepii Noua excepie trebuie s moteneasc una deja existent n ierarhia Java. Toate excepiile create de utilizator trebuie s fac parte din ierarhia Exceptions, i nu Error, care este rezervat pentru erorile interne ale mainii virtuale Java. Cautai o excepie care seamn cu cea de care avei nevoie. Clasele de excepie posed, de obicei, doi constructori: primul nu primete niciun argument, iar al doilea primete ca argument un ir. n ultimul caz trebuie s apelai metoda super() n constructorul respectiv, pentru a v asigura c irul este dispus corespunztor n cadrul excepiei. Clasele de excepi arat ca toate celelalte clase. Putei s le definii n propriul fiier surs i s le compilai, aa cum procedai cu toate celelalte clase: public class ExceptieExploziiSolare extends Exception{ public ExceptieExploziiSolare() {} public ExceptieExploziiSolare(String mesaj){ super(mesaj); } } Combinarea clauzelor throws, try i throw Dac folosii numai clauzele try i catch, nu putei transmite mai departe excepia, iar dac folosii clauza throws, nu mai avei ocazia de a trata excepia. Dac dorii att tratarea excepiei, ct i transmitere ei ctre apelant, folosii toate cele trei mecanisme: clauza throws, instruciunea try i instruciunea throw pentru resemnalarea excepiei. public void metodaExceptie() throws IOException{ CititorMesaje cm = new CititorMesaje(); try{ cm.incarcaAntet(); }catch (IOException e){ //se trateaza exceptia de intrare/iesire throw e; //se resemnaleaza exceptia } }

Exemplu. S scriem un program Java care simuleaz un client ntr-o cafenea virtual care bea o cafea. S considerm dou situaii de excepie care pot aprea n momentul n care client i savureaz cafeaua. Ierarhia de clase de excepie este prezentat mai jos:

smaranda.belciug@inf.ucv.ro

Dac, din pcate, clientul descoper c butura este rece, programul trebuie s semnaleze o TooColdException. Pe de alt parte, dac el descoper c butura este prea fierbinte, programul trebuie s semnaleze o TooHotException. Aceste situaii pot fi excepii, deoarece (s sperm) nu sunt situaii normale ntr-o cafenea.
// TemperatureException.java class TemperatureException extends Exception { } // TooColdException.java class TooColdException extends TemperatureException { } // TooHotException.java class TooHotException extends TemperatureException { }

Urmtorul cod arat cum o clas care reprezint clientul, clasa VirtualPerson, poate semnala excepii.
// VirtualPerson.java class VirtualPerson { private static final int tooCold = 65; private static final int tooHot = 85; public void drinkCoffee(CoffeeCup cup) throws TooColdException, TooHotException { int temperature = cup.getTemperature(); if (temperature <= tooCold) { throw new TooColdException(); } else if (temperature >= tooHot) { throw new TooHotException(); } //... } //... } // CoffeeCup.java class CoffeeCup { // 75 degrees Celsius: the best temperature for coffee private int temperature = 75;

smaranda.belciug@inf.ucv.ro
public void setTemperature(int val) { temperature = val; } public int getTemperature() { return temperature; } //... }

S presupunem c programul cere un argument n linia de comand, un string care apoi s fie convertit ntr-un int. Dac string-ul reprezint un integer, parseInt() va returna valoarea sa. Daca string-ul nu reprezint un integer, parseInt() va semnala NumberFormatException.
//Example1.java class Example1 { public static void main(String[] args) { int temperature = 0; if (args.length > 0) { try { temperature = Integer.parseInt(args[0]); } catch(NumberFormatException e) { System.out.println( "Va rog introduceti un numar intreg."); return; } } else { System.out.println( "Va rog introducei temperatura ca argument."); return; } CoffeeCup cup = new CoffeeCup(); cup.setTemperature(temperature); VirtualPerson cust = new VirtualPerson(); VirtualCafe.serveCustomer(cust, cup); } } // VirtualCafe.java class VirtualCafe { public static void serveCustomer(VirtualPerson cust, CoffeeCup cup) { try { cust.drinkCoffee(cup); System.out.println("Cafeaua este perfecta."); } catch (TooColdException e) { System.out.println("Cafeaua este prea rece."); // rezolva problema cu clientul nervos... } catch (TooHotException e) { System.out.println("Cafeaua este prea fierbinte."); // rezolva problema cu clientul nervos... } } }

smaranda.belciug@inf.ucv.ro

// VirtualCafe.java class VirtualCafe { public static void serveCustomer(VirtualPerson cust, CoffeeCup cup) { try { cust.drinkCoffee(cup); System.out.println("Cafeaua e perfecta."); } catch (TemperatureException e) { System.out.println("Cafeaua este ori prea fierbinte ori prea rece"); // rezolva problema cu clientul nervos... } } } // VirtualCafe.java class VirtualCafe { public static void serveCustomer(VirtualPerson cust, CoffeeCup cup) { try { cust.drinkCoffee(cup); System.out.println("Cafeaua e perfecta."); } catch (TemperatureException e) { System.out.println("Cafeaua este ori prea fierbinte ori prea rece"); // rezolva problema cu clientul nervos... } // ACEASTA NU SE VA COMPILA, DEOARECE NU SE VA AJUNGE //NICIODATA AICI catch (TooColdException e) { System.out.println("Cafeaua este prea rece."); } } } // VirtualCafe.java class VirtualCafe { public static void serveCustomer(VirtualPerson cust, CoffeeCup cup) { try { cust.drinkCoffee(cup); System.out.println("Cafeaua este perfecta."); } catch (TooColdException e) { System.out.println("Cafeaua este prea rece."); // rezolva problema cu clientul nervos... catch (TemperatureException e) { // This catches TooHotException as well // as TemperatureException. System.out.println( "Ceva e neregula cu temperatura cafelei."); // rezolva problema cu clientul nervos... } } } // VirtualPerson.java class VirtualPerson {

10

smaranda.belciug@inf.ucv.ro
public void drinkCoffee(CoffeeCup cup) throws TooColdException, TemperatureException, UnusualTasteException { try { int i = (int) (Math.random() * 4.0); switch (i) { case 0: throw new TooHotException(); case 1: throw new TooColdException(); case 2: throw new UnusualTasteException(); default: throw new TemperatureException(); } } catch (TooHotException e) { System.out.println("Cafeaua e prea fierbinte."); // Clientul va astepta pana cand cafeaua se raceste } } //... }

Daca i = 0, se va intercepta exceptia TooHoTException, daca difera de 0, Java va semnala o excepie metodei care a invocat metoda drinkCoffee(). O method invocation stack (sau call stack) este o list de metode invocate de un thread (laboratorul 8) care ncepe cu prima metod invocat i se sfrete cu metoda curent.
// VirtualPerson.java class VirtualPerson { public void drinkCoffee(CoffeeCup cup) { try { int i = (int) (Math.random() * 4.0); switch (i) { case 0: throw new TooHotException(); case 1: throw new TooColdException(); case 2: throw new UnusualTasteException(); default: System.out.println("Cafeaua e grozava!"); } } catch (TooHotException e) { System.out.println("Cafeaua e prea fierbinte."); } catch (TooColdException e) { System.out.println("Cafeaua este prea rece."); } catch (UnusualTasteException e) { System.out.println("Cafeaua este prea tare."); } finally { System.out.println("Putei sa-mi aducei o alt cafea?"); } } //... }

11

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