Tratarea erorilor

 

Excepţiile reprezintă mecanismul java folosit pentru tratarea erorilor ce apar īn timpul execuţiei programelor. Excepţiile pot fi privite ca nişte evenimente ce pot fi generate şi tratate īn timpul rulării unei aplicaţii. Excepţiile sunt modelate īn java ca şi clase sub forma unei ierarhii ce are la bază clasa Throwable (vezi Figura  1).

 

Figura 1. Ierarhia claselor pentru tratarea exceptiilor.

 

Īn java există trei tipuri de erori:

-          clasa Error : modelează excepţii speciale generate īn timpul rulării aplicaţiilor java, care sunt īn general dependente de echipamentele hardware pe care rulează aplicaţiile java. Programatorul nu trebuie să trateze astfel de erori īn cadrul unei aplicaţii obişnuite.

-          clasa Excepţion : modelează excepţii standard ce trebuiesc tratate de către aplicaţiile java. Īn java tratarea excepţiilor este obligatorie – compilatorul constrānge programatorul să introducă blocuri de tratare a excepţiilor atunci cānd foloseşte metode care pot arunca aceste excepţii.

-          Clasa RuntimeException : modelează excepţii ce nu trebuiesc tratate de către programator.

 

Aruncarea excepţiilor

 

Pentru a genera sau a arunca o excepţie o metodă trebuie să definiească clauza throws sub forma:

 

void metoda() throws Eception1, Exception2{

..

if(conditie) throw new Exception1(...);.

...

if(conditie) throw new Exception2(...);

...

return;

}

 

Generarea şi aruncarea unei excepţii dintr-o metodă se face folosind instrucţiunea throw urmată de excepţia care va fi aruncată.

 

Tratarea excepţiilor.

 

In momentul eplării unei metode ce conţine o clauză throws, apelul acelei metode trebui inclus īn cadrul unui bloc try, urmat de unul sau mai multe blocuri catch responsabile cu tratarea excepţiilor sub forma:

 

try{

            metoda();

}

catch(Exception1 e1){...}

catch(Exception e2){...}

 

Īn momentul īn care o excepţie este generată de către o metodă cursul normal de execuţie este īntrerup şi se sare la unul dintre blocurile de tratare a excepţiilor. Excepţia este prinsă de acel bloc catch al cărei excepţii asociate se potriveşte cu excepţia aruncă.

 

Excepţiile sunt prinse īn cadrul blocurilor try{...} şi sunt tratate īn cadrul blocurilor catch(...).

 

Īn cadrul blocurilor pentru tratarea excepţiilor poate fi adăugat opţional şi un bloc finally sub forma:

 

try{

}

catch(Exception e1){...}

finally{...}

 

Instrucţiunile din blocul finally sunt executate īntotdeauna indiferent de modul de finalizare a instrucţiunilor din blocul try (fie că a fost generată excepţie, fie că nu a fost generată excepţie).

 

Din cadrul unui bloc catch, o excepţie poate fi aruncată mai departe sub forma:

 

try{

...

}

catch(Exception e1){ throw e1;}

 

 

Crearea propriilor excepţii.

 

Programatorul are posibilitatea de a defini propriile sale excepţii prin extinderea clasei Exception.

 

public class TestMyException {

            public static void f() throws MyException {

                  System.out.println("Exceptie in f()");

                  throw new MyException();

            }

            public static void g() throws MyException {

                  System.out.println("Exceptie in g()");

                  throw new MyException("aruncata din g()");

            }

            public static void main(String[] args) {

            try {

                  f();

            } catch(MyException e) {e.printStackTrace();}

            try {

                  g();

            } catch(MyException e) {e.printStackTrace();}

        }

      }

 

class MyException extends Exception {

      public MyException() {}

      public MyException(String msg) {

            super(msg);

      }

}

 

Exerciţiu: Testaţi aplicaţia de mai sus. Adăugaţi o nouă clasă de tip excepţie şi testaţi folosirea acesteia.

 

Īn continuare este prezentată o aplicaţie ce exemplifică noţiunile prezentate mai sus.

 

public class CoffeTest {

      public static void main(String[] args) {

            CofeeMaker mk = new CofeeMaker();

            CofeeDrinker d = new CofeeDrinker();

           

            for(int i = 0;i<15;i++){

                  Cofee c = mk.makeCofee();

                  try {

                        d.drinkCofee(c);

                  } catch (TemperatureException e) {

                        System.out.println("Exception:"+e.getMessage()+" temp="+e.getTemp());

                  } catch (ConcentrationException e) {

                        System.out.println("Exception:"+e.getMessage()+" conc="+e.getConc());

                  }

                  finally{

                        System.out.println("Throw the cofee cup.\n");

                  }

            }    

      }

}//.class

 

class CofeeMaker {

      Cofee makeCofee(){

            System.out.println("Make a coffe");

            int t = (int)(Math.random()*100);

            int c = (int)(Math.random()*100);

            Cofee cofee = new Cofee(t,c);

            return cofee;

      }

     

}//.class

 

class Cofee{

      private int temp;

      private int conc;

     

      Cofee(int t,int c){temp = t;conc = c;}

      int getTemp(){return temp;}

      int getConc(){return conc;}

      public String toString(){return "[cofee temperature="+temp+":concentration="+conc+"]";}

}//.class

 

class CofeeDrinker{

      void drinkCofee(Cofee c) throws TemperatureException, ConcentrationException{

            if(c.getTemp()>60)

                  throw new TemperatureException(c.getTemp(),"Cofee is to hot!");

            if(c.getConc()>50)

                  throw new ConcentrationException(c.getConc(),"Cofee concentration to high!");         

            System.out.println("Drink cofee:"+c);

      }

}//.class

 

class TemperatureException extends Exception{

      int t;

      public TemperatureException(int t,String msg) {

            super(msg);

            this.t = t;

      }

     

      int getTemp(){

            return t;

      }

}//.class

 

class ConcentrationException extends Exception{

      int c;

      public ConcentrationException(int c,String msg) {

            super(msg);

            this.c = c;

      }

     

      int getConc(){

            return c;

      }

}//.class

 

Exerciţiu: Construiţi un proiect Eclipse şi adăugaţi īn cadrul acestuia aplicaţia de mai sus. Testaţi aplicaţia.

 

Exerciţiu: Īn varianta curentă clasa CofeeMaker este astfel construită īncāt permite generarea unui numar infinit de obiecte de tip Cofee. Modificaţi aplicaţia astfel īncāt un CofeeMaker să permită crearea unui număr limitat de obiecte de tip Cofee, şi īn momentul īn care acest număr limită a fost atins, metoda makeCofee() să returneze o excepţie specifică.

 

Prinderea tuturor excepţiilor cu un singur bloc catch.

 

Deoarece toate excepţiile au la bază clasa Exception, un bloc try{...} poate fi urmat doar de un singur bloc catch coreszpunzător clasei Exception, care va asigura prinderea tuturor excepţiilor indiferent de tipul lor. Nu se recomandă folosirea acestei metode, şi este bine ca fiecare tip de excepţie să fie tratată īn mod individual.

 

Secvenţa de construire a obiectelor de tip Cofee ar putea fi rescrisă astfel:

 

try {

      d.drinkCofee(c);

} catch (Exception e) {

      System.out.println("Exception:"+e.getMessage());

}

 

Excepţii de tip RuntimeException

 

Excepţiile care sunt construite prin extinderea clasei Exception trebuiesc obligatoriu tratate după cum s-a văzut īn secţiunile anterioare. Īn java există posibilitatea de a construi excepţii pentru care nu trebuiesc construite blocuri de tratare a excepţiilor. Aceste excepţii au la bază clasa RuntimeException.

 

Excepţiile de tip RuntimeException modelează erori de programare care nu sunt generate de o cauză externă. De exemplu īncercarea de apelarea a unei metode din cadrul unui obiect neiniţializat va genera excepţia NullPointerException. Īncercarea de accesare a unui element inexistent dintr-un vector va genera excepţia  ArrayIndexOutOfBoundException.

 

String s;

s.toString();

 

Aceste excepţii pot apărea oriunde īn program si pot fi extrem de numeroase iar īncercarea de "prindere" a lor ar fi extrem de anevoioasa. Din acest motiv compilatorul permite ca aceste excepţii sa rămānă ne tratate, tratarea lor ne fiind īnsă ilegala.

 

Exerciţiu: Studiaţi articolul Exception-Handling Antipatterns.