User Tools

Site Tools


Problem constructing authldap
laboratoare:exceptii
Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:exceptii [2016/12/12 09:00]
Andrei Vasiliu [JUnit]
laboratoare:exceptii [2019/11/30 19:55] (current)
Tudor Paraschivescu [Resurse]
Line 1: Line 1:
-JUnit & Excepții = += Excepții =
- +
-* Responsabili:​ Mihaela Pinzaru, Cristi Vasile +
-* Data publicării:​ 11.12.2016 +
-* Data ultimei modificări:​ 11.12.2016+
  
 == Obiective == == Obiective ==
  
-  * familiarizarea cu noţiunea de **Unit Testing** şi folosirea framework-ului **JUnit** pentru realizarea testării 
   * înţelegerea conceptului de **excepţie** şi utilizarea corectă a mecanismelor de **generare şi tratare** a excepţiilor puse la dispoziţie de limbajul / maşina virtuală Java   * înţelegerea conceptului de **excepţie** şi utilizarea corectă a mecanismelor de **generare şi tratare** a excepţiilor puse la dispoziţie de limbajul / maşina virtuală Java
  
-== Unit testing == +== Introducere ​==
- +
-Unit testing-ul s-a impus în ultima perioadă în dezvoltarea proiectelor scrise în limbajul Java şi nu numai, pe măsura apariţiei unor utilitare gratuite de testare a claselor, care au contribuit la creşterea vitezei de programare şi la micşorarea semnificativă a numărului de bug-uri. +
- +
-Printre avantajele folosirii framework-ului JUnit se numără: +
-* îmbunătăţirea vitezei de scriere a codului şi creşterea calităţii acestuia +
-* clasele de test sunt uşor de scris şi modificat pe măsură ce codul sursă se măreşte, putând fi compilate împreună cu codul sursă al proiectului +
-* clasele de test JUnit pot fi rulate automat (în suită), rezultatele fiind vizibile imediat +
-* clasele de test măresc încrederea programatorului în codul sursă scris şi îi permit să urmărească mai uşor cerinţele de implementare ale proiectului +
-* testele pot fi scrise înaintea implementării,​ fapt ce garantează înţelegerea funcţionalităţii de către dezvoltator +
- +
-=== JUnit === +
- +
-Reprezintă un framework de Unit Testing pentru Java.  +
- +
- +
-**Exemplu:​** +
- +
-<code java Student.java>​ +
- +
-public class Student { +
- +
-    private String name; +
-    private String age; +
- +
-    public Student(String name, String age) { +
-        this.name = name; +
-        this.age = age; +
-    } +
- +
-    public String getName() { +
-        return name; +
-    } +
- +
-    public void setName(String name) { +
-        this.name = name; +
-    } +
- +
-    public String getAge() { +
-        return age; +
-    } +
- +
-    public void setAge(String age) { +
-        this.age = age; +
-    } +
- +
-+
- +
-</​code>​ +
- +
-<code java Grupa.java>​ +
-import java.util.ArrayList;​ +
-import java.util.List;​ +
- +
-public class Grupa { +
- +
-    List<​Student>​ students; +
-  +
-    Grupa () { +
-        students = new ArrayList<​Student>​();​ +
-    } +
- +
-    public List<​Student>​ getStudents() { +
-        return students; +
-    } +
- +
-    public void setStudents(List<​Student>​ students) { +
-        this.students = students; +
-    } +
- +
-    public void addStudent(Student student) { +
-        students.add(student);​ +
-    } +
- +
-    public Student getStudent(String name) { +
-        for (Student st : students) { +
-            if (null != st.getName() && st.getName().equals(name)) { +
-                return st; +
-            } +
-        } +
-        return null; +
-    } +
- +
-    public boolean areStudentsInGroup() { +
-        if (0 == students.size()) { +
-            return false; +
-        } +
-        return true; +
-    } +
- +
-+
-</​code>​ +
- +
-<code java Test.java>​ +
-import org.junit.Assert;​ +
-import org.junit.Before;​ +
- +
-public class Test { +
-    private Grupa grupa; +
- +
-    @Before +
-    public void setup() { +
-        grupa = new Grupa(); +
-    } +
- +
-    @org.junit.Test +
-    public void testNoStudentInGroup() { +
-        Assert.assertEquals(false,​ grupa.areStudentsInGroup());​ +
-    } +
- +
-    @org.junit.Test +
-    public void testAddStudent() { +
-        Student st = new Student("​Elena",​ "​11"​);​ +
-        grupa.addStudent(st);​ +
- +
-        Assert.assertTrue(grupa.getStudent("​Elena"​).equals(st));​ +
-    } +
-    @After void tearDown() { +
-        grupa = null; +
-    } +
- +
-+
-</​code>​ +
- +
-**Observaţii:​** +
-* fiecare metodă de test are adnotarea: ''​@Test''​ +
-* metodele de **setUp** (având adnotarea: ''​@Before''​) şi **tearDown** (având adnotarea: ''​@After''​) se apelează înainte, respectiv după fiecare test. Se întrebuinţează pentru iniţializarea/​eliberarea resurselor ce constituie mediul de testare, evitându-se totodată duplicarea codului şi respectându-se principiul de independenţă a testelor. Pentru exemplul dat ordinea este: +
-    * ''​@Before setUp''​ +
-    * ''​@Test testNoStudentInGroup''​ +
-    * ''​@After tearDown''​ +
-    * ''​@Before setUp''​ +
-    * ''​@Test testAddStudent''​ +
-    * ''​@After tearDown''​ +
-* În contextul moștenirii dacă ChildTest extends ParentTest ordinea de execuţie este urmatoarea:​ +
-    * ''​**ParentTest** @Before setUp''​ +
-    * ''​ChildTest @Before setUpSub''​ +
-    * ''​ChildTest @Test testChild1''​ +
-    * ''​ChildTest @After tearDownSub''​ +
-    * ''​**ParentTest** @After tearDown''​ +
-* Pentru compararea rezultatului aşteptat cu rezultatul curent se folosesc apeluri ''​assert'':​ +
-    * ''​assertTrue''​ +
-    * ''​assertFalse''​ +
-    * ''​assertEquals''​ +
-    * ''​assertNull''​ / ''​assertNotNull''​ +
-* **Rulare teste**: Click dreapta clasă test -> //Run as// -> //Junit test// +
-* **Rulare test**: Selectare test -> click dreapta ->  //Run as// -> //Junit test// +
- +
- +
-<note important>​ +
-În cadrul laboratorului vom folosi framework-ul JUnit adăugând fişierele [[http://​search.maven.org/​remotecontent?​filepath=junit/​junit/​4.12/​junit-4.12.jar|junit.jar]] şi [[https://​storage.googleapis.com/​google-code-archive-downloads/​v2/​code.google.com/​hamcrest/​hamcrest-all-1.3.jar|hamcrest-all-1.3.jar]] cu acesta la proiectele create. +
- +
-Pentru a importa un //jar// într-un proiect din ''​Eclipse''​ parcurgeţi următorii paşi: //click dreapta proiect// -> //Build path// -> //Configure build path// -> //​Libraries//​ -> //Add jars (Add external jars)//. +
-</​note>​ +
- +
-Câteodată avem nevoie să testăm funcționalitatea unor clase ce folosesc metode din alte clase netestate sau care nu pot fi testate. De asemenea, există cazuri în care vrem sa testăm comportamentul clasei în situații extreme sau foarte greu de replicat (erori de disc, epuizarea spațiului pe disc, obținerea unei anumite valorii în cazul in care folosim generatoare random). +
- +
-Pentru a rezolva ușor aceste necesități putem folosi obiecte de tip **mock**. Aceste obiecte simulează comporatamentul clasei mock-uite și sunt controlate din interiorul unit testelor. Pentru mai multe detalii puteți consulta pagina [[http://​en.wikipedia.org/​wiki/​Mock_object|Mock Object]]. +
- +
-<note tip> +
-În Java pentru a implementa mock-uri puteți folosi framework-ul **JMock**. Un scurt tutorial de instalare si folosire găsiți [[http://​www.askeygeek.com/​jmock-for-beginners/​|aici]]. Pentru exemple mai detaliate puteţi consulta [[http://​www.jmock.org/​cookbook.html|cookbook-ul]] pus la dispozitie pe site-ul jmock.org. +
-</​note>​ +
- +
-== Excepţii ​==+
  
 În esenţă, o **excepţie** este un **eveniment** care se produce în timpul execuţiei unui program şi care **perturbă** fluxul normal al instrucţiunilor acestuia. În esenţă, o **excepţie** este un **eveniment** care se produce în timpul execuţiei unui program şi care **perturbă** fluxul normal al instrucţiunilor acestuia.
Line 178: Line 11:
 De exemplu, în cadrul unui program care copiază un fişier, astfel de evenimente excepţionale pot fi: De exemplu, în cadrul unui program care copiază un fişier, astfel de evenimente excepţionale pot fi:
 * absenţa fişierului pe care vrem să-l copiem * absenţa fişierului pe care vrem să-l copiem
-* imposibilitatea de a-l citi din cauza permisiunilor insuficiente ​sau din cauza unei zone invalide de pe hard-disk+* imposibilitatea de a-l citi din cauza permisiunilor insuficiente
 * probleme cauzate de accesul concurent la fişier * probleme cauzate de accesul concurent la fişier
  
Line 192: Line 25:
 if (openResult == FILE_NOT_FOUND) { if (openResult == FILE_NOT_FOUND) {
     // handle error     // handle error
-} else if (openResult == INUFFICIENT_PERMISSIONS) {+} else if (openResult == INSUFFICIENT_PERMISSIONS) {
     // handle error     // handle error
 } else {// SUCCESS } else {// SUCCESS
Line 214: Line 47:
 } catch (FILE_NOT_FOUND) { } catch (FILE_NOT_FOUND) {
     // handle error     // handle error
-} catch (INUFFICIENT_PERMISSIONS) {+} catch (INSUFFICIENT_PERMISSIONS) {
     // handle error     // handle error
 } catch (DISK_ERROR) { } catch (DISK_ERROR) {
Line 227: Line 60:
 Când o eroare se produce într-o funcţie, aceasta creează un **obiect excepţie** şi îl pasează către ''​runtime system''​. Un astfel de obiect conţine informaţii despre situaţia apărută: Când o eroare se produce într-o funcţie, aceasta creează un **obiect excepţie** şi îl pasează către ''​runtime system''​. Un astfel de obiect conţine informaţii despre situaţia apărută:
 * **tipul** de excepţie * **tipul** de excepţie
-* **stiva de apeluri** (stack trace): punctul din program unde a intervenit excepţia, reprezentat sub forma lanţului de metode ​(obţinut prin invocarea succesivă a metodelor din alte metode) ​în care programul se află în acel moment+* **stiva de apeluri** (stack trace): punctul din program unde a intervenit excepţia, reprezentat sub forma lanţului de metode în care programul se află în acel moment
  
 Pasarea menţionată mai sus poartă numele de **aruncarea** (throwing) unei excepţii. ​ Pasarea menţionată mai sus poartă numele de **aruncarea** (throwing) unei excepţii. ​
Line 249: Line 82:
  
 În realitate, clasa ''​Exception''​ este părintele majorităţii claselor excepţie din Java. Enumerăm câteva excepţii standard: În realitate, clasa ''​Exception''​ este părintele majorităţii claselor excepţie din Java. Enumerăm câteva excepţii standard:
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​IndexOutOfBoundsException.html|IndexOutOfBoundsException]]:​ este aruncată când un index asociat unei liste sau unui vector depăşeşte dimensiunea colecţiei respective. +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​IndexOutOfBoundsException.html|IndexOutOfBoundsException]]:​ este aruncată când un index asociat unei liste sau unui vector depăşeşte dimensiunea colecţiei respective. 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​NullPointerException.html|NullPointerException]]:​ este aruncată când se accesează un obiect neinstanţiat (''​null''​). +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​NullPointerException.html|NullPointerException]]:​ este aruncată când se accesează un obiect neinstanţiat (''​null''​). 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​util/​NoSuchElementException.html|NoSuchElementException]]:​ este aruncată când se apelează next pe un ''​Iterator''​ care nu mai conţine un element următor.+* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​NoSuchElementException.html|NoSuchElementException]]:​ este aruncată când se apelează next pe un ''​Iterator''​ care nu mai conţine un element următor.
  
 În momentul în care se instanţiază un obiect-excepţie,​ în acesta se reţine întregul lanţ de apeluri de funcţii prin care s-a ajuns la instrucţiunea curentă. Această succesiune se numeşte **stack trace** şi se poate afişa prin apelul [[http://​docs.oracle.com/​javase/​1.4.2/​docs/​api/​java/​lang/​Throwable.html#​printStackTrace()|e.printStackTrace()]],​ unde ''​e''​ este obiectul excepţie. În momentul în care se instanţiază un obiect-excepţie,​ în acesta se reţine întregul lanţ de apeluri de funcţii prin care s-a ajuns la instrucţiunea curentă. Această succesiune se numeşte **stack trace** şi se poate afişa prin apelul [[http://​docs.oracle.com/​javase/​1.4.2/​docs/​api/​java/​lang/​Throwable.html#​printStackTrace()|e.printStackTrace()]],​ unde ''​e''​ este obiectul excepţie.
Line 284: Line 117:
 Funcţia ''​f''​ va arunca întotdeauna o excepţie (din cauza că ''​l''​ este mereu ''​null''​). Observaţi cu atenţie funcţia ''​catchFunction'':​ Funcţia ''​f''​ va arunca întotdeauna o excepţie (din cauza că ''​l''​ este mereu ''​null''​). Observaţi cu atenţie funcţia ''​catchFunction'':​
 * în interiorul său a fost definit un bloc ''​try'',​ în interiorul căruia se apelează ''​f''​. De obicei, pentru a **prinde** o excepţie, trebuie să specificăm o zonă în care aşteptăm ca excepţia să se producă (**guarded region**). Această zonă este introdusă prin ''​try''​. * în interiorul său a fost definit un bloc ''​try'',​ în interiorul căruia se apelează ''​f''​. De obicei, pentru a **prinde** o excepţie, trebuie să specificăm o zonă în care aşteptăm ca excepţia să se producă (**guarded region**). Această zonă este introdusă prin ''​try''​.
-* în continuare, avem blocul ''​catch''​ (''​Exception e''​). La producerea excepţiei, blocul ''​catch''​ corespunzător va fi executat. În cazul nostru se va afişa mesajul ''"​S-a generat o excepţie"''​.+* în continuare, avem blocul ''​catch''​ (''​Exception e''​). La producerea excepţiei, blocul ''​catch''​ corespunzător va fi executat. În cazul nostru se va afişa mesajul ''"​S-a generat o excepţie"''​. După aceea, programul va continua să ruleze normal în continuare.
  
 Observaţi un alt exemplu: Observaţi un alt exemplu:
  
 <code java> <code java>
-public void f() throws ​MyExceptionWeirdException ​+public void f() throws ​NullPointerExceptionEmptyListException ​
-    List<​String>​ l = null+    List<​String>​ l = generateList()
-                 +  
-    if (null == l+    if (== null
-        throw new MyException(); +        throw new NullPointerException(); 
- +  
-    throw new WeirdException("This exception never gets thrown"​);+    ​if (l.isEmpty()) 
 +        ​throw new EmptyListException();
 } }
 + 
 public void catchFunction() { public void catchFunction() {
     try {     try {
         f();         f();
-    } catch (MyException ​e) {+    } catch (NullPointerException ​e) {
         System.out.println("​Null Pointer Exception found!"​);​         System.out.println("​Null Pointer Exception found!"​);​
-    } catch (WeirdException ​e) { +    } catch (EmptyListException ​e) { 
-        System.out.println("​WeirdException ​found!"​);​+        System.out.println("​Empty List Exception ​found!"​);​
     }     }
 } }
 </​code>​ </​code>​
  
-În acest exemplu funcţia ''​f''​ a fost modificată astfel încât să arunce ​''​MyException''​. Observaţi faptul că în ''​catchFunction''​ avem două blocuri ''​catch''​. ​Cum excepţia aruncată de ''​f''​ este de tip ''​MyException'',​ numai primul ​bloc ''​catch''​ se va executa.+În acest exemplu funcţia ''​f''​ a fost modificată astfel încât să existe posibilitatea de a arunca ''​NullPointerException''​ sau ''​EmptyListException''​. Observaţi faptul că în ''​catchFunction''​ avem două blocuri ''​catch''​. ​În funcție de excepția aruncată de ''​f'',​ numai un singur ​bloc ''​catch''​ se va executa.
  
 Prin urmare: Prin urmare:
-* putem specifica **porţiuni** de cod pentru **tratarea** excepţiilor folosind blocurile ''​try''​ şi ''​catch''​ +* putem defini mai multe blocuri ​''​catch''​ pentru a implementa o tratare preferenţială a excepţiilor,​ în funcţie de tipul acestora 
-* putem defini **mai multe** blocuri catch pentru a implementa o tratare ​**preferenţială** a excepţiilor,​ în funcţie de tipul acestora+* în cazul aruncării unei excepții într-un bloc ''​try'',​ se va intra **într-un singur bloc** ''​catch''​ (cel aferent excepției aruncate)
  
 <note important>​ <note important>​
Line 371: Line 205:
 Nu toate excepţiile trebuie prinse cu ''​try-catch''​. Pentru a înțelege de ce, să analizăm clasificarea ​ excepţiilor:​ Nu toate excepţiile trebuie prinse cu ''​try-catch''​. Pentru a înțelege de ce, să analizăm clasificarea ​ excepţiilor:​
  
-{{ :​laboratoare:​lab9:tipurideexceptii.png?​nolink&​400 |Tipuri de excepţii}}+{{ :​laboratoare:​exceptii:exceptions-hierarchy.png?​nolink&​500 |Tipuri de excepţii}}
  
-**Checked exceptions**,​ ce corespund clasei [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Exception.html|Exception]]:​ +Clasa **[[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Throwable.html|Throwable]]**:​ 
-  * Acestea sunt excepţii pe care o aplicaţie bine scrisă ar trebui să le **prindă**,​ şi să permită **continuarea** rulării programului.+  * Superclasa tuturor erorilor și excepțiilor din Java. 
 +  * Doar obiectele ce extind această clasă pot fi aruncate de către JVM sau prin instrucțiunea ''​throw''​. 
 +  * Numai această clasă sau una dintre subclasele sale pot fi tipul de argument într-o clauză ''​catch''​. 
 + 
 +**Checked exceptions**,​ ce corespund clasei [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Exception.html|Exception]]:​ 
 +  * aplicaţie bine scrisă ar trebui să le **prindă**,​ şi să permită **continuarea** rulării programului.
   * Să luăm ca exemplu un program care cere utilizatorului un nume de fişier (pentru a-l deschide). În mod normal, utilizatorul va introduce un nume de fişier care există şi care poate fi deschis. Există insă posibilitatea ca utilizatorul să greşească,​ caz în care se va arunca o excepţie ''​FileNotFoundException''​.   * Să luăm ca exemplu un program care cere utilizatorului un nume de fişier (pentru a-l deschide). În mod normal, utilizatorul va introduce un nume de fişier care există şi care poate fi deschis. Există insă posibilitatea ca utilizatorul să greşească,​ caz în care se va arunca o excepţie ''​FileNotFoundException''​.
-  * Un program bine scris va prinde această excepţie, va afişa utilizatorului un mesaj de eroare, şi îi va permite ​acestuia (eventualsă reintroducă un nou nume de fişier.+  * Un program bine scris va prinde această excepţie, va afişa utilizatorului un mesaj de eroare, şi îi va permite eventual să reintroducă un nou nume de fişier.
  
-**Errors**, ce corespund clasei [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Error.html|Error]]:​+**Errors**, ce corespund clasei [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Error.html|Error]]:​
   * Acestea definesc situaţii excepţionale declanşate de factori **externi** aplicaţiei,​ pe care aceasta nu le poate anticipa şi nu-şi poate reveni, dacă se produc.   * Acestea definesc situaţii excepţionale declanşate de factori **externi** aplicaţiei,​ pe care aceasta nu le poate anticipa şi nu-şi poate reveni, dacă se produc.
-  * Spre exemplu, ​tentativa ​de a citi un fişier care nu poate fi deschis din cauza unei defecţiuni hardware (sau eroare OS), va arunca ''​IOError''​. +  * Spre exemplu, ​alocarea unui obiect foarte mare (un vector cu milioane ​de elemente), poate arunca ''​OutOfMemoryError''​. 
-  * Aplicaţia poate încerca să prindă această ​excepţie, pentru a anunţa utilizatorul despre problema apărută; după această însă, programul va eşua (afişând eventual ''​stack trace''​).+  * Aplicaţia poate încerca să prindă această ​eroare, pentru a anunţa utilizatorul despre problema apărută; după această însă, programul va eşua (afişând eventual ''​stack trace''​).
  
-**Runtime Exceptions**,​ ce corespund clasei [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​RuntimeException.html|RuntimeException]]:​+**Runtime Exceptions**,​ ce corespund clasei [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​RuntimeException.html|RuntimeException]]:​
   * Ca şi erorile, acestea sunt condiţii excepţionale,​ însă spre **deosebire** de **erori**, ele sunt declanşate de factori **interni** aplicaţiei. Aplicaţia nu poate anticipa, şi nu îşi poate reveni dacă acestea sunt aruncate.   * Ca şi erorile, acestea sunt condiţii excepţionale,​ însă spre **deosebire** de **erori**, ele sunt declanşate de factori **interni** aplicaţiei. Aplicaţia nu poate anticipa, şi nu îşi poate reveni dacă acestea sunt aruncate.
   * **Runtime exceptions** sunt produse de diverse bug-uri de programare (erori de logică în aplicaţie, folosire necorespunzătoare a unui API, etc).   * **Runtime exceptions** sunt produse de diverse bug-uri de programare (erori de logică în aplicaţie, folosire necorespunzătoare a unui API, etc).
Line 391: Line 230:
 Excepţiile **checked** sunt cele **prinse** de blocurile ''​try-catch''​. Toate excepţiile sunt **checked** cu excepţia celor de tip **Error**, **RuntimeException** şi subclasele acestora, adica cele de tip **unchecked**. Excepţiile **checked** sunt cele **prinse** de blocurile ''​try-catch''​. Toate excepţiile sunt **checked** cu excepţia celor de tip **Error**, **RuntimeException** şi subclasele acestora, adica cele de tip **unchecked**.
  
-Excepţiile **error** nu trebuie (în mod obligatoriu) prinse folosind ''​try-catch''​. Opţional, programatorul poate alege să le prindă. 
  
-Excepţiile **runtime** nu trebuie ​(în mod obligatoriuprinse folosind ​''​try-catch''​. ​Ele sunt de tip **RuntimeException**. Aţi întâlnit deja exemple de excepţii runtime, în urma diferitelor neatenţii de programare: ''​NullPointerException'',​ ''​ArrayIndexOutOfBoundsException'',​ etc.+Nu este indicată prinderea excepţiilor **unchecked** (de tip [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Error.html|Error]] sau [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​RuntimeException.html|RuntimeException]]cu ''​try-catch''​. 
 </​note>​ </​note>​
  
Line 445: Line 284:
 } }
 </​code>​ </​code>​
 +</​note>​
 +
 +<note tip>
 +Din **Java 7**, a fost adăugată construcția ''​try-with-resources'',​ care ne permite să declarăm resursele într-un bloc de ''​try'',​ cu asigurarea că resursele vor fi închise după executarea acelui bloc. Resursele declarate trebuie să implementeze interfața [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​AutoCloseable.html|AutoCloseable]].
 +
 +<code java >
 +try (PrintWriter writer = new PrintWriter(file)) {
 +    writer.println("​Hello World"​);​
 +}
 +</​code>​
 +
 </​note>​ </​note>​
  
Line 450: Line 300:
 Metodele suprascrise (overriden) pot arunca **numai** excepţiile specificate de metoda din **clasa de bază** sau excepţii **derivate** din acestea. Metodele suprascrise (overriden) pot arunca **numai** excepţiile specificate de metoda din **clasa de bază** sau excepţii **derivate** din acestea.
  
-== Exerciţii ​==+== Chain-of-responsibility Pattern ​==
  
-  ​**(2p)** Creaţclasa  ''​Animal''​ şi clasa ''​Zoo''​Clasa ''​Zoo'' ​conţine un vector ​de animaleImplementaţi metodele: ''​addAnimal(Animal a)''​''​removeAnimal(Animal a)'',​ ''​boolean areAnimals(),​ getAnimals()'',​ ''​size()''​. Creaţi ​clasa ''​Test''​ unde veţi verifica diverse __scenarii__:​ +În proiectarea orientată pe obiect, pattern-ul "​Chain-of-responsibility" ​(lanț de responsabilitateeste un model de design constând dintr-o sursă de obiecte de comandă șo serie de obiecte de procesareFiecare obiect de procesare ​conține logică care definește tipurile de obiecte de comandă pe care le poate gestiona; restul sunt transferate către următorul obiect de procesare din lanț. De asemenea, există ​un mecanism pentru adăugarea ​de noi obiecte de procesare la sfârșitul acestui lanțAstfellanțul de responsabilitate este versiune orientată pe obiecte a ''​if ... else if ..else if ...... else ... endif''​, cu avantajul că blocurile condiție-acțiune pot fi dinamic rearanjate șreconfigurate la timpul de execuție. 
-    * La rularea fiecărei metode veti instanţia clasa ''​Zoo''​. + 
-    * Metoda ​''​testAddAnimal''​ - adaugă un obiect ''​Animal''​ şverifică daca adăugarea a avut loc cu succesFolosiţi**''​assertEquals''​** +{{ :laboratoare:​exceptii:​chain-of-responsibility.jpg?​nolink |Chain-of-responsibility}} 
-    * Metoda ''​testRemoveAnimal'' ​folosiţi **''​assertTrue''​** + 
-    * Metoda ''​testAreAnimalsInZoo'' ​testul pică dacă metoda returnează ''​false''​. //Hint//**''​Assert.fail()''​**  +Într-o variantă a modelului standard al lanțului de responsabilitate,​ un handler poate acționa ca un [[laboratoare:tutorial-doubledispatch|dispatcher]],​ capabil să trimită comenzi în diverse direcții, formând un tree de responsabilități. În unele cazuri, ​acest lucru poate apărea recursivcu procesarea obiectelor care apelează obiecte de procesare ​de nivel superior cu comenzi care încearcă să rezolve ​parte mai mică a problemei; ​în acest cazrecurența continuă până când comanda este procesată, sau întregul arbore a fost explorat. Un interpretor XML ar putea funcționa în acest mod. 
-    * Metoda ''​testGetAnimals'' ​adăugaţi două obiecte ''​Animal''​. Verificaţi ca adăugarea a avut loc cu succes. Folosiţ**assertFalse**. + 
-  - **(2p)** Acest exerciţiu urmăreşte identificarea unor cazuri ​de teststrict pe baza specificaţieiîn absenţa accesului la codul sursă şi a cunoaşterii modului intern ​de funcţionare a sistemului. Se consideră o clasa ''​GeometricForms''​ avand un constructor ce primeste un String ce poate fi unul din valorile enum-ului ''​Forms''​. +Modelul lanțului ​de responsabilitate este aproape identic cu modelul decoratoruluidiferența fiind că pentru decoratortoate clasele se ocupă de cerereiar pentru lanțul de responsabilitateexact una dintre clasele ​din lanț se ocupă de cerere
-    * Adăugaţi ​în build path-ul proiectului clasele din scheletul de laborator. + 
-    * Metodele ''​isTriangle''​''​isCircle''​ si ''​isRectangle''​ au drept scop evaluarea stării obiectului ''​GeometricForms''​. +== Exerciţii == 
-    * Creaţi un scenariu de testare pentru această clasă, prin implementarea propriilor cazuri ​de testareîntr-o clasă ''​GeometricFormsTest''​. +  - **(2p)** ​Citițde la **stdin** ​linie de text și afișați-o la **stdout** folosind BufferedReader-ul definit în schelet. Nu uitați ​să afișați un mesaj sugestiv în cazul apariției unei excepții și să închidețresursa ​după terminarea folosirii acesteiaFolosițconstrucția ''​try-with-resources''​ sau ''​try-catch-finally''​
-    * Construiţi teste specializateorientate pe o anumită funcţionalitate. De exempluîn cadrul unui testverificaţi doar una din cele 3 metode+  - **(3p)**  Definiţi o clasă care să implementeze operaţii pe numere **double**. Operaţiile vor arunca excepţii. ​Clasa va trebui să implementeze interfața ​''​Calculator'',​ ce conţine trei metode: 
-    * <code java> +    * ''​add'':​ primeşte ​două numere ​şi întoarce un ''​double''​ 
-public enum Forms { +    * ''​divide'':​ primeşte ​două numere ​şi întoarce un ''​double''​ 
-   ​TRIANGLE,​ CIRCLE, RECTANGLE +    * ''​average'':​ primeşte o colecţie ce conţine obiecte ''​double'',​ şi întoarce media acestora ca un numar de tip ''​double''​. Pentru calculul mediei, sunt folosite ​metodele ​''​add''​ şi ''​divide''​. 
-+    * Metodele pot arunca ​următoarele excepții (definite în interfața ''​Calculator''​):​ 
-</​code>​ +      * ''​NullParameterException'':​ este aruncată dacă vreunul din parametrii primiți este ''​null''​ 
-  - **(2p)** ​ ​Scrieţi o metodă (scurtă) care să genereze [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​OutOfMemoryError.html|OutOfMemoryError]] şo alta care să genereze [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​StackOverflowError.html|StackOverflowError]]. ​ Verificaţposibilitatea de a continua rularea ​după interceptarea acestei eroriComparaţrăspunsul cu posibilitatea de a realiza acelaşi lucru într-un limbaj compilat, ce rulează direct pe platforma gazdă (ca C)+      * ''​OverflowException'':​ este aruncată dacă suma a două numere ​egală cu ''​Double.POSITIVE_INFINITY''​ 
-  - **(2p)**  Definiţi o clasă care să implementeze operaţii pe numere **întregi**. Operaţiile vor arunca excepţii. ​Scrieţi clasa ''​Calculator'',​ ce conţine trei metode: +      * ''​UnderflowException'':​ este aruncată dacă suma a două numere ​e egală cu ''​Double.NEGATIVE_INFINITY''​ 
-    * ''​add'':​ primeşte ​doi întregi ​şi întoarce un **întreg** +    * Completați metoda ''​main''​ din clasa ''​MainEx2'',​ evidențiind prin teste toate cazurile posibile care generează excepţii. 
-    * ''​divide'':​ primeşte ​doi întregi ​şi întoarce un **întreg** +  - **(1p)**  ​Care este alegerea firească ​pentru exercițiul trecut: excepţii **checked** sau **unchecked**?​ De ce? Consideraţi că, pentru un utilizator care doreşte efectuarea de operaţii aritmetice, **singurul** mecanism disponibil este cel oferit de clasa ''​Calculator''​. Discutați cu asistentul. 
-    * ''​average'':​ primeşte o colecţie ce conţine obiecte ''​Integer'',​ şi întoarce media acestora ca un numar de tip **întreg**. Pentru calculul mediei, sunt folosite ​operaţiile ​''​add''​ şi ''​divide''​. +  - **(4p)** Dorim să implementăm un ''​Logger''​ pe baza pattern-ului Chain-of-responsibility,​ definit mai sus, pe care îl vom folosi să păstram un jurnal de evenimente al unui program (vezi adaptarea în Referințe):​ 
-    * Definiţi ​următoarele excepţii şi îmbogăţiţi corespunzător definiţia metodei ​''​add''​: +    ​**(1p)** Creați enumerația ''​LogLevel'',​ ce va acționa ca un [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​EnumSet.html|bitwise flag]], care va conține valorile - ''​Info,​ Debug, Warning, Error, FunctionalMessage,​ FunctionalError''​. Această enumerație va expune șo metodă statică ''​all()''​ care va întoarce o colecție de ''​EnumSet<​LogLevel>''​ în care vor fi toate valorile de mai sus (Hint: ''​EnumSet.allOf()''​). [[https://​www.geeksforgeeks.org/​enumset-class-java/​|Exemplu]] practic de folosire. 
-    * ''​OverflowException'':​ este aruncată dacă suma celor doua numere depăşeşte ''​Integer.MAX_VALUE''​ +    - **(1p)** Creați o clasă abstractă ''​LoggerBase'':​ 
-    * ''​UnderflowException'':​ este aruncată dacă suma celor doua numere ​este mai mică decat ''​Integer.MIN_VALUE''​ +      - va primi în constructor un obiect de tip ''​EnumSet<​LogLevel>'' ​care va defini pentru ce nivele de log se va afisa mesajul 
-    * Care este alegerea firească: excepţii **checked** sau **unchecked**?​ De ce? Consideraţi că, pentru un utilizator care doreşte efectuarea de operaţii aritmetice, **singurul** mecanism disponibil este cel oferit de clasa ''​Calculator''​. +      - va păstra o referință către următorul ''​LoggerBase''​ la care se trimite mesajul 
-    * Evidenţiaţprin teste toate cazurile posibile ​care generează excepţii+      - va expune o metodă publică ''​setNext''​ ce va primi un ''​LoggerBase''​ și va seta următorul delegat din lista de responsabilitate 
-  - **(2p)** ​Demonstraţîntr-un program execuţia blocului ​''​finally'' ​chiar şi în cazul unui ''​return''​ din metoda.+      - va defini o metodă abstractă protected ''​writeMessage''​ ce va primi mesajul care trebuie afișat 
 +      - va expune o metodă publică ''​message''​ ce va primi mesajul care trebuie afișat și o severitate de tip ''​LogLevel''​Dacă instanța de logger conține această severitate în colecția primite în constructor,​ atunci se va apela metoda ''​writeMessage''​. Apoi se vor pasa mesajul și severitatea către următorul delegat din lista de responsabilitate (dacă există unul) 
 +    - **(2p)** ​Definițclasele de mai jos care vor extinde ''​LoggerBase''​ și implementa metoda ''​writeMessage'':​ 
 +      ​ConsoleLogger - care va scrie toate tipurile de ''​LogLevel'' ​(Hint: ''​all()''​) șva prefixa mesajele cu ''​[Console] ''​ 
 +      - EmailLogger - care va scrie doar tipurile ''​FunctionalMessage''​ și ''​FunctionalError''​ și va prefixa mesajele cu ''​[Email] ''​ 
 +      - FileLogger - care va scrie doar tipurile ''​Warning''​ și ''​Error''​ și va prefixa mesajele cu ''​[File] ''​ 
 +      - Hint: ''​EnumSet.of()''​ 
 +      - Completați cele 2 **TODO**-uri rămase ​în metoda ​''​main''​ din clasa ''​MainEx4''​.
  
 == Resurse == == Resurse ==
  
 +* {{laboratoare:​exceptii:​skel-lab-exceptii.zip|Schelet}}
 +* {{laboratoare:​exceptii:​sol-lab-exceptii.zip|Soluție}}
 * <​html><​a class="​media mediafile mf_pdf"​ href="/​poo/​laboratoare/​exceptii?​do=export_pdf">​PDF laborator</​a></​html>​ * <​html><​a class="​media mediafile mf_pdf"​ href="/​poo/​laboratoare/​exceptii?​do=export_pdf">​PDF laborator</​a></​html>​
-* [[http://​search.maven.org/​remotecontent?​filepath=junit/​junit/​4.12/​junit-4.12.jar|Junit Download]] +
-* [[http://​search.maven.org/​remotecontent?​filepath=org/​hamcrest/​hamcrest-core/​1.3/​hamcrest-core-1.3.jar|Hamcrest Core]] +
-* {{:​laboratoare:​lab9:​lab-skel.zip|Schelet}} +
-* {{|Soluții}}+
  
 == Referinţe == == Referinţe ==
  
-* [[http://​en.wikipedia.org/​wiki/​Mock_object|Mock Object]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Exception.html|Exception]] 
-* [[http://​www.askeygeek.com/​jmock-for-beginners/​|JMock for beginners]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Error.html|Error]] 
-* [[http://​www.jmock.org/​cookbook.html|JMock Cookbook]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​RuntimeException.html|RuntimeException]] 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Exception.html|Exception]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​NullPointerException.html|NullPointerException]] 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Error.html|Error]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​IndexOutOfBoundsException.html|IndexOutOfBoundsException]] 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​RuntimeException.html|RuntimeException]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​NoSuchElementException.html|NoSuchElementException]] 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​NullPointerException.html|NullPointerException]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​OutOfMemoryError.html|OutOfMemoryError]] 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​IndexOutOfBoundsException.html|IndexOutOfBoundsException]] +* [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​StackOverflowError.html|StackOverflowError]] 
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​util/​NoSuchElementException.html|NoSuchElementException]] +* [[https://​en.wikipedia.org/​wiki/​Chain-of-responsibility_pattern#​C#​_example|Adaptarea exercițiului după exemplul din C#]]
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​OutOfMemoryError.html|OutOfMemoryError]] +
-* [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​StackOverflowError.html|StackOverflowError]]+
  
laboratoare/exceptii.1481526015.txt.gz · Last modified: 2016/12/12 09:00 (external edit)