Differences

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

Link to this comparison view

poo-ca-cd:laboratoare:exceptii [2020/10/03 12:43]
amalia.palaghiu [Introducere]
poo-ca-cd:laboratoare:exceptii [2024/01/14 19:22] (current)
aghiorghita [Exerciţii]
Line 1: Line 1:
-===== Excepții =====+===== Laboratorul 12: Excepții ===== 
 + 
 +**Video introductiv:​** [[https://​youtu.be/​WhoDX_wkkhM | link]]
  
 ==== Obiective ==== ==== Obiective ====
Line 86: Line 88:
   * [[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.   * [[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/​8/​docs/​api/​java/​lang/​Throwable.html#​printStackTrace--|e.printStackTrace()]],​ unde ''​e''​ este obiectul excepţie.
  
 === Prinderea excepţiilor === === Prinderea excepţiilor ===
Line 117: Line 119:
 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"''​. După aceea, programul va continua să ruleze normal în continuare.+  * î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 ''"​Exception found!"''​. După aceea, programul va continua să ruleze normal în continuare.
  
 Observaţi un alt exemplu: Observaţi un alt exemplu:
Line 287: Line 289:
  
 <note tip> <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]].+Din **Java 7**, a fost adăugată construcția ''​try-with-resources'',​ care ne permite să declarăm resursele într-un bloc ''​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 > <code java >
Line 307: Line 309:
  
  
-Într-o variantă a modelului standard al lanțului de responsabilitate,​ un handler poate acționa ca un [[:​poo-ca-cd:​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 recursiv, cu procesarea obiectelor care apelează obiecte de procesare de nivel superior cu comenzi care încearcă să rezolve o parte mai mică a problemei; în acest caz, recurenț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+Într-o variantă a modelului standard al lanțului de responsabilitate,​ un handler poate acționa ca un [[:​poo-ca-cd:​laboratoare:​tutorial-doubledispatch|dispatcher]],​ capabil să trimită comenzi în diverse direcții, formând un arbore ​de responsabilități ​(tree of responsibility). În unele cazuri, acest lucru poate apărea recursiv, cu procesarea obiectelor care apelează obiecte de procesare de nivel superior cu comenzi care încearcă să rezolve o parte mai mică a problemei; în acest caz, recurenț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.
- +
-Modelul lanțului de responsabilitate este aproape identic cu modelul decoratorului,​ diferența fiind că pentru decorator, toate clasele se ocupă de cerere, iar pentru lanțul de responsabilitate,​ exact una dintre clasele din lanț se ocupă de cerere.+
  
 ==== Exerciţii ==== ==== Exerciţii ====
-  - **(2p)** Citiți de la **stdin** o 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ți resursa după terminarea folosirii acesteia. Folosiți construcția ''​try-with-resources''​ sau ''​try-catch-finally''​. +  - **(4p)**  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 ''​CalculatorBase'',​ ce conţine trei 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: +     ​* ''​add'':​ primeşte două numere şi întoarce un ''​double''​ 
-    * ''​add'':​ primeşte două numere şi întoarce un ''​double''​ +     ​ ''​divide'':​ primeşte două numere şi întoarce un ''​double''​ 
-    * ''​divide'':​ primeşte două numere şi întoarce un ''​double''​ +     ​ ''​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'' ​!! .
-    * ''​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''​):​     * Metodele pot arunca următoarele excepții (definite în interfața ''​Calculator''​):​
-      * ''​NullParameterException'':​ este aruncată dacă vreunul din parametrii primiți este ''​null''​ +      * ''​NullParameterException'':​ este aruncată dacă vreunul din parametrii primiți este ''​null''​; 
-      * ''​OverflowException'':​ este aruncată dacă suma a două numere e egală cu ''​Double.POSITIVE_INFINITY''​ +      * ''​OverflowException'':​ este aruncată dacă suma a două numere e egală cu ''​Double.POSITIVE_INFINITY''​; 
-      * ''​UnderflowException'':​ este aruncată dacă suma a două numere e egală cu ''​Double.NEGATIVE_INFINITY''​+      * ''​UnderflowException'':​ este aruncată dacă suma a două numere e egală cu ''​Double.NEGATIVE_INFINITY''​.
     * Completați metoda ''​main''​ din clasa ''​MainEx2'',​ evidențiind prin teste toate cazurile posibile care generează excepţii.     * Completați metoda ''​main''​ din clasa ''​MainEx2'',​ evidențiind prin teste toate cazurile posibile care generează excepţii.
-  - **(1p)**  Care este alegerea firească pentru exercițiul trecut: ​excepţii **checked** sau **unchecked**?​ De ce? Consideraţi ​, pentru ​un utilizator ​care doreşte efectuarea de operaţii aritmetice, ​**singurul** mecanism disponibil este cel oferit ​de clasa ''​Calculator''​. ​Discutați cu asistentul+  - **(4p)** Vom realiza o mini librărie online în care putem adăuga cărți cumpărându-le și din care putem să extragem o carte deja existentă. 
-  - **(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)+        - Definește clasa ''​Book''​ care are parametrii title, author, genre și price. 
-    **(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 și 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+        - Definește două noi excepții care extind clasa Exception:​ 
-    **(1p)** ​Creați o clasă abstractă ''​LoggerBase'':​ +          ​''​NotEnoughMoneyException'',​ care e aruncată atunci când utilizatorul nu are bani suficienți pentru a cumpăra o carte 
-      ​- ​va primi în constructor un obiect de tip ''​EnumSet<​LogLevel>​'' ​care va defini pentru ce nivele de log se va afisa mesajul +          ​''​NoSuchBookException'',​ care e aruncată atunci când cartea dorită nu se găsește în librărie. 
-      ​- ​va păstra o referință către următorul ​''​LoggerBase'' ​la care se trimite mesajul +        - Definește clasa ''​OnlineLibrary''​ care are: 
-      ​- ​va expune o metodă publică ''​setNext''​ ce va primi un ''​LoggerBase'' ​și va seta următorul delegat din lista de responsabilitate +          ​doi parametrii: o listă de rți și bugetul utilizatorului 
-      ​- ​va defini o metodă abstractă protected ''​writeMessage''​ ce va primi mesajul care trebuie afișat +          * un constructor ​care primește bugetul inițial al utilizatorului 
-      ​- ​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) +          ​metodele: 
-    **(2p)** ​Definiți clasele de mai jos care vor extinde ​''​LoggerBase'' ​și implementa metoda ''​writeMessage''​+           ''​addBook''​ - primește o carte și o adaugă în librărie dacă utilizatorul are fonduri suficiente 
-      - ConsoleLogger ​- care va scrie toate tipurile de ''​LogLevel'' ​(Hint: ​''​all()''​) și va prefixa mesajele cu ''​[Console] ''​ +           ''​getBook''​ - returnează cartea dorită, dacă aceasta se află în librărie. 
-      ​- ​EmailLogger - care va scrie doar tipurile ​''​FunctionalMessage'' ​și ''​FunctionalError'' ​și va prefixa mesajele cu ''​[Email] ''​ +        - În metoda ''​Main''​ să se realizeze TODO-urile:​ 
-      ​- ​FileLogger - care va scrie doar tipurile ​''​Warning'' ​și ''​Error'' ​și va prefixa mesajele cu ''​[File] ''​ +            ​*''​TODO1''​ - adaugă lista de cărți în librărie 
-      - Hint: ''​EnumSet.of()''​ +            *''​TODO2'' ​- ia cartea book4 din librărieDacă nu există, adaug-o. 
-      ​- Completați cele 2 **TODO**-uri rămase în metoda ​''​main'' ​din clasa ''​MainEx4''​+        * Atenție la tratarea excepțiilor! (A se afișa un mesaj corespunzător fiecărui caz, ca în exemplu)
- +    - **(2p)** Dorim să implementăm un ''​Logger''​ pe baza pattern-ului Chain-of-responsibility,​ definit ​în laborator, pe care îl vom folosi să păstram un jurnal de evenimente al unui program: 
-==== Resurse ==== +        - Creați enumerația ''​LogLevel'',​ ce va acționa ca un bitwise flag, care va conține
- +            * valorile - ''​Info''​''​Debug''​''​Warning''​''​Error''​''​FunctionalMessage''​''​FunctionalError''​. 
-  * {{poo-ca-cd:​laboratoare:​exceptii:​skel-lab-exceptii.zip|Schelet}} +            * Această enumerație va expune și 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()''​). 
-  * {{poo-ca-cd:​laboratoare:​exceptii:​sol-lab-exceptii.zip|Soluție}} +        - Creați o clasă abstractă ''​LoggerBase'' ​care
-  * <​html><​a class="​media mediafile mf_pdf"​ href="/​poo/​laboratoare/​exceptii?​do=export_pdf">​PDF laborator</​a></​html>​ +            ​* ​va primi în constructor un obiect de tip EnumSet<​LogLevel>​ care va defini pentru ce nivele de log se va afisa mesajul 
 +            ​* ​va păstra o referință către următorul LoggerBase la care se trimite mesajul 
 +            ​* ​va expune o metodă publică ''​setNext''​ ce va primi un LoggerBase și va seta următorul delegat din lista de responsabilitate 
 +            ​* ​va defini o metodă abstractă protected ''​writeMessage''​ ce va primi mesajul care trebuie afișat ​și afișează mesajul în cauză 
 +            ​* ​va expune o metodă publică ''​message''​ ce va primi mesajul care trebuie afișat și o severitate de tip LogLevel ​(adică Info, Debug, Warning, Error, FunctionalMessage sau FunctionalError). Dacă instanța de logger conține această severitate în colecția ​primită ​î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) 
 +        - Definiți clasele de mai jos care vor extinde LoggerBase și implementa metoda ​writeMessage:​ 
 +            * ''​ConsoleLogger''​ - care va scrie toate tipurile de LogLevel (Hint: all()) și 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]''​ 
 +        - Completați cele 2 TODO-uri rămase în metoda main din clasa Main. (Hint: ​''​EnumSet.of()'' ​pentru constructori)
  
 ==== Referinţe ==== ==== Referinţe ====
poo-ca-cd/laboratoare/exceptii.1601718214.txt.gz · Last modified: 2020/10/03 12:43 by amalia.palaghiu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0