Sunteți pe pagina 1din 10

Pachete Java, Tratarea excepțiilor în Java

Obiective:
- definirea și utilizarea pachetelor;
- ințelegerea mecanismelor de tratare a excepțiilor; excepții simple; excepții multiple;
- throw vs. throws;
- metode care semnalizează excepții;
- clase proprii de tip excepție;
- asertiuni;

Pachete Java

Un pachet Java este o colecţie de clase şi interfeţe grupate în general după funcţionalitate cu scopul de a beneficia de
protecţia oferită de acest tip de grupare.
Un pachet Java se declară folosind cuvântul cheie package. Declararea unui pachet Java trebuie făcută înainte de orice
altă instrucţiune din program (înainte şi de secţiunea de importări ale altor pachete şi clase din antetul programului).
Sintaxa:
package nume_pachet;

Pentru a putea fi folosite ca atare, fişierele sursă şi bytecode rezultate prin compilarea componentelor unui pachet trebuie
stocate într-un subdirector care poartă numele pachetului. Astfel ele vor fi găsite de JVM în momentul importării în
aplicaţii terţe (bineînţeles, cu respectarea tuturor regulilor referitoare la classpath).
Pachetele facilitează un mecanism de interacțiune între clase prin asociere, clasele din același pachet fiind accesibile între
ele (friendly access).

Excepții Java

O excepţie nu reprezintă o eroare de compilare şi este dată de o situaţie anormală ce poate să apară în timpul execuţiei
unei aplicaţii Java (program stand-alone, applet, etc.) cerând aplicaţiei:
• să îşi încheie imediat execuţia (în caz de eroare şi în lipsa unui mecanism de gestionare a situaţiei apărute)
• să execute o acţiune specială cu acea excepţie (evitând blocarea sistemului, dacă s-a prevăzut un mod de a
gestiona situaţia apărută)
Cele mai multe excepţii care se întâlnesc apar ca răspuns la unele condiţii de eroare cum ar fi :
• împărţirea cu zero a unui număr întreg
• depăşirea domeniului unei variabile
• acces nepermis la elementele unui tablou, etc.

Când interpretorul întâlneşte o asemenea situaţie, se creează un obiect excepţie care memorează starea aplicaţiei din acel
moment şi care va cauza un salt la o zonă dată de un indicator de excepţie (handler), dependent de natura excepţiei.
Dacă nu e definit nici un indicator pentru o anumită excepţie, executarea programului sare la sfârşitul metodei în care a
apărut excepţia. Acest mecanism poate continua, urcând astfel prin întreaga ierarhie de metode a aplicaţiei, până în
momentul în care se ajunge în vârful acesteia (de exemplu metoda main()). Rezultatul este stoparea procesului software
respectiv, de multe ori aceasta însemnând oprirea totală a aplicaţiei.

Excepţii de tip eroare

Sunt subclase ale java.lang.Error.


Acestea nu sunt de obicei în sarcina programatorilor şi constituie de multe ori erori de sistem (depăşiri de memorie, etc.)

Excepţii specifice

În această categorie intră problemele care pot să apară într-un program corect care conţine date incorecte în contextul
dat.
Acestea sunt subclase ale java.lang.Exception (mai puţin java.lang.RuntimeException).

Excepţii la rulare

Excepţiile la rulare constituie o alta categorie de excepţii iar aici intră de obicei bug-urile de programare (indecşi de şiruri
în afara limitelor, variabile neiniţializate, etc.) și apar în clasa și subclasele java.lang.RuntimeException. Ele nu
trebuie neapărat tratate de utilizator, dar e recomandat. Ele se întalnesc sub denumirea de unchecked exceptions.

Exceptiile generate de operații de Intrare/Ieșire precum și cele apărute în grafica Java AWT (etc.) trebuie tratate de
programator în mod obligatoriu, altfel compilatorul va produce mesaje de erorare. Ele se numesc, checked exceptions.

Clasa java.lang.Throwable este clasa de bază pentru excepțiile din Java.


Metodele din clasa java.lang.Throwable se propagă în toată ierarhia de clase de tip excepție şi sunt esenţiale
pentru funcţionarea mecanismelor de tratare a excepţiilor.

Constructori:

• Throwable()
=> construieşte un nou obiect, având null drept mesaj de eroare.
• Throwable(String message)
=> construieşte un obiect care are mesajul de eroare specificat că parametru
• Throwable(String message, Throwable cause)
=> construieşte un obiect care are mesajul de eroare şi cauza specificate ca parametri
• Throwable(Throwable cause)
=> construieşte un obiect care are cauza specificată ca parametru

Metode membre:

• Throwable fillInStackTrace()
=> completează stiva de execuţie a programului
• Throwable getCause()
=> returnează cauza excepţiei în cauză sau null dacă cauza este inexistentă sau necunoscută
• String getLocalizedMessage()
=> crează o descriere localizată a obiectului în cauză
• String getMessage()
=> returnează un mesaj detaliat care descrie excepţia curentă
• StackTraceElement[] getStackTrace()
=> pune la dispoziţie accesul la elementele conţinute de stiva de execuţie a programului
• Throwable initCause(Throwable cause)
=> iniţializează cauza obiectului curent cu valoarea parametrului primit
• void printStackTrace()
=> tipăreşte (în fluxul standard de eroare) informaţia stocată în stiva de execuţie a programului
• void printStackTrace(PrintStream s)
=> tipăreşte informaţia stocată în stiva de execuţie a programului în fluxul de date de ieşire primit ca parametru
• void printStackTrace(PrintWriter s)
=> tipăreşte informaţia stocată în stiva de execuţie a programului în fluxul de date de ieşire de tip writer specificat
• void setStackTrace(StackTraceElement[] stackTrace)
=> setează elementele care vor fi returnate sau tipărite ulterior la apelul getStackTrace() şi printStackTrace()
• String toString()
=> returnează o descriere textuală a obiectului curent
Mecanismele de tratare a excepţiilor în Java

Pentru a intercepta şi trata o excepţie, se foloseşte instrucţiunea try/catch/finally.

Sintaxa:
try{
//instrucţiuni care pot genera excepţii
}
catch(Tip_1_Excepţie nume_exceptie1){
//bloc de tratare a tipului 1 de excepţie
}
catch(Tip_2_Excepţie nume_exceptie2){
//bloc de tratare a tipului 2 de excepţie
}
//...
catch(Tip_N_Excepţie nume_exceptieN){
//bloc de tratare a tipului N de excepţie
}
finally{
//bloc opțional de instrucţiuni care se execută oricum
}

Există mai multe reguli care guvernează tratarea excepţiilor multiple:


• excepţiile de tipuri mai specifice trebuie plasate înaintea celor mai generale
• un singur bloc catch şi numai unul (şi anume primul întâlnit care se potriveşte ca tip cu excepţia curentă) va fi
executat la apariţia unei excepţii
• se pot combina în același catch, folosind operatorul OR (I), mai multe tratări de excepții dacă modul de tratare
este același. (try { … } catch(Eclass1 | Eclass2 e) {…})
• exista posibilitatea de a defini într-o zonă de gardă (try…catch( )) resurse care sunt valide doar în această zonă.
Acest mecanism e numit try with resources.
try (BufferedReader reader = …) {
doSomeIOWith(reader);

} catch(…) {…}

Mecanismul de delegare a excepţiilor în Java

Sunt însă cazuri în care se permite delegarea excepțiilor, adică ”semnalizarea-aruncarea -lansarea” lor in mod explicit. La
lansarea locală se folosește throw, iar pentru a pasa excepția mai sus în ierarhia software a aplicaţiei respective se
folosește cuvantul cheie throws (în antetul metodei).

Suprascrierea metodelor şi tratarea excepţiilor

În cazul în care o clasă derivată suprascrie o metodă a clasei de bază, pe lângă restricţiile impuse specificatorilor de
vizibilitate, Java prevede faptul că metodele care suprascriu metodele originale nu pot semnaliza alte excepţii decât cele
ale metodei originale. Este permisă însă declararea unei metode care nu semnalizează nici o excepţie, deşi metoda
originală făcea acest lucru.

Definirea propriilor clase de tip excepţie

Programatorul este liber să definească propriile clase de tip excepţie, pentru că apoi să le folosească după necesităţi.
Mecanismul cel mai des întâlnit este alegerea unei clase de tip excepţie deja existente şi derivarea ei. Se poate alege clasa
cea mai apropiată de necesităţi, sau se poate porni chiar de la java.lang.Throwable.

Aserțiuni

Aserțiune Java = expresie booleană care este presupusă a fi adevărată în momentul execuției.
Implicit sunt dezactivate în Java, se folosesc în faza de testare de catre developer.

Mod de utilizare:

assert expresie1; unde expresie1 are valoare booleană

assert expresie1 : expresie2; unde expresie1 are valoare booleană iar expresie2 = expresie care are valoare sau funcție
care returnează orice în afară de void; va fi executată în cazul expresie1==false;

OBS: Suportarea aserțiunilor e specificată în momentul rulării:

> java -ea p1

În Eclipse trebuie setat: VM arguments –ea

Când expresia aserțiunii are valoarea false, va fi generată o excepție AssertionError (de tip eroare, unchecked).

La execuția normală a unui program scris corect nu ar trebui să apară AssertionErrors. Aceste erori ar trebui să indice
doar bug-uri în implementare. În asemenea situații programul ar trebui să se oprească, să poată fi văzut mesajul de
eroare și să se poată localiza sursa problemei.

Aserțiunile se folosesc pentru a verifica:

- dacă o valoare este într-un anumit domeniu

- dacă se ajunge într-o anumită zonă a programului

- dacă starea unui obiect respectă o anumită constrângere

- ce trebuie să fie adevărat în momentul apelului unei metode sau după apelul acesteia
Exemple

Ex.1 Declarare pachet propriu


package pack1; // declarare pachet (fisier sursa: KeyboardReader.java, localizat
// in directorul pack1)

import java.util.Scanner;

public class KeyboardReader{

Scanner scanner;

public KeyboardReader(){
scanner = new Scanner(System.in);
}

public int readInt(){


int rez;

System.out.print("Scrie o valoare intreaga: ");


rez = scanner.nextInt();

return rez;
}

public void close(){


scanner.close();
}
}

Ex. 1 Utilizare pachet propriu


import pack1.KeyboardReader;

class Test {

public static void main(String... args){


KeyboardReader reader = new KeyboardReader();

int a = reader.readInt();
System.out.println("Valoarea citita: " + a);

reader.close();

}
}

Ex. 2 Metoda care semnalizeaza exceptii (declarare si apel)


public class Exceptions_01{
public float metodaPericuloasa(int x,int j) throws ArithmeticException{
//float rez = (float)x/j; //Infinity
float rez = x/j;

return rez;
}

public static void main (String[] args){


int y = 3;
float rez;

Exceptions_01 ob = new Exceptions_01();

System.out.println("Inceput program");

for(int i=-2;i<3;i++){
rez = 0;
boolean ok = true;
try{
rez = ob.metodaPericuloasa (y,i);
}
catch(ArithmeticException e){
ok = false;
System.out .println("Impartire cu zero");
}
if(ok)
System.out.println(y + " : " + i + " = "+rez);
}
}
}

Ex. 3 Catch-uri multiple

class Test {

public void suma(int n, Scanner scanner) throws NumberFormatException,


ArrayIndexOutOfBoundsException{

int values[] = new int[3];


int s = 0;
for(int i=0; i<n; i++){
values[i] = Integer.parseInt(scanner.nextLine());
}

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


s += values[i];
}

System.out.println("Rezultatul adunarii: "+s);


}

public static void main(String... args){


int n;
Test tester = new Test();
Scanner scanner = new Scanner(System.in);

System.out.println("Cate valori adunam? ");


n = Integer.parseInt(scanner.nextLine());

try {
tester.suma(n, scanner);

}
catch (NumberFormatException e) {
System.out.println("Valoare introdusa in format incorect...");
}
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Prea multe valori pentru un sir prea mic...");
}
finally {
System.out.println("Finally va fi rulat oricum.");
}
}
}

Ex. 4 Clase proprii de tip exceptie

import java.lang.Throwable;

class MyException extends Throwable{


//constructor
public MyException(){
//apelul constructorului clasei de baza
super("Sirul de caractere nu are voie sa fie abc!!!");
}
}

class X{
void metoda(String text) throws MyException{
if(text.equalsIgnoreCase("abc")){
throw new MyException();
}
else{
System.out.println("Sirul de caractere "+text+" corespunde.");
}
}
}

class Test{
public static void main(String args[]){
String text_interzis = new String("abc");
String text_acceptat = new String("xyz");

X ob1 = new X();


try{
ob1.metoda(text_interzis);
}
catch(MyException ex1){
ex1.printStackTrace();
}

try{
ob1.metoda(text_acceptat);
}
catch(MyException ex2){
ex2.toString();
}
}
}

Ex. 5 Aserțiuni- invarianți interni (setare Eclipse : VM arguments –ea, si linie cda :> java -ea AssertD)

import java.util.Scanner;

public class AssertD{

public static void main( String args[ ] ){


System.out.print( "Enter a number between 0 and 10: " );
@SuppressWarnings("resource")
int number = new Scanner( System.in ).nextInt();
//assert that the absolute value is >= 0 and less then 10 as internal
//invariant
assert ( number >= 0 && number <= 10 ) : "bad number: " + number;
//for false
System.out.printf( "You entered %d\n", number );
} // end main
} // end class
Lucru individual

Complexitate *

1. Scrieti un program Java care defineste un sir de valori de tip double care vor fi citite de la tastatura. Tratati exceptia
data de accesarea unui element cu index negativ sau mai mare decat indexul ultimului element din sir
(ArrayIndexOutOfBoundsException). Afisati un mesaj corespunzator in momentul detectarii exceptiei. Considerati o
matrice (cu numar de coloane fix pentru fiecare linie) si tratati exceptia posibil a aparea. Considerati si cazul in care
matricea are numar diferit de coloane la fiecare linie.

2. Scrieți o aplicație Java care, în cadrul metodei main( ), conține o secvență de cod care poate să lanseze excepții de tip
ArithmeticException, ArrayIndexOutOfBoundsException, NullPointerException, NumberFormatException și altele pe care
considerați că e util să le testați. Afișați în cadrul blocurilor catch mesajul generat de aceste excepții. În blocul finally,
afișați mesajul ”Am prins sau nu excepții”.

3. Definiți un pachet care declară interfața Int1 (2 variabile întregi și o metodă numita sum( ) care returnează suma a doi
întregi). În pachet mai există clasa Class1 (2 variabile protected de tip double, constructor, metode accesor și mutator
pentru variabilele din clasă). În alt fișier sursă se adaugă în același pachet o nouă interfață numită Int2 (2 variabile de tip
double și o metodă numită product( ) care returnează produsul a două valori de tip double).
Într-un fișier sursă distinct, importați tot ce conține pachetul definit anterior și definiți o clasă numită Class2 care este
derivată din Class1 și care implementează ambele interfețe Int1 și Int2. Instanțiați Class2 și aplicați metodele disponibile
pentru a calcula suma și produsul unor variabile citite de la tastatură.

4. Creați o clasă derivată din Exception, numită SuperExceptie. O a doua clasă ExceptieMaiMica este derivată din
SuperExceptie. În constructorii claselor afisați un mesaj ce indică excepția generată. În cadrul unei alte clase creați o
metodă a( ) ce semnalizeaza (aruncă) o excepție de tip ExceptieMaiMica și o metodă b( ) ce semnalizeaza o excepție de
tip SuperExceptie.
În cadrul metodei main( ) apelați aceste metode și încercați să determinați tipul de excepție semnalizată, precum și dacă
blocul catch aferent tipului de exceptie ExceptieMaiMica poate prinde o SuperExcepție.

Complexitate **

5. Scrieți o aplicație ce verifică dacă 3 puncte aleatoare formează un triunghi obtuzunghic. Dacă nu este îndeplinită
condiția, se aruncă o excepție specifică: TriunghiAscutitunghic, TriunghiDreptunghic. Dacă cele 3 puncte se află pe
aceeași dreaptă sau dacă segmentele pe care le determină nu pot forma un triunghi, se aruncă o excepție
TriunghiImposibil, iar în blocul catch aferent, se afișează un mesaj corespunzător și se aruncă o excepție de tip
RuntimeException.

6. Scrieți o aplicație Java ce implementează o excepție numită Saturat. Această excepție este generată atunci când
saturația unei culori este peste valoarea 90 în spațiul HSV. Creați o metodă ce generează aleator culori în spațiul RGB și
face conversia acestora la spațiul HSB/HSV. (https://www.cs.rit.edu/~ncs/color/t_convert.html) . Dacă după conversie,
saturația culorii depășește valoarea 90, regenerați culoarea (In faza de testare folositi o asertiune pentru a verifica
aceasta conditie ca si invariant intern). După 10 regenerări consecutive, dacă nu se obține o culoare nesaturată, se
aruncă o excepție.

7. Definiti un pachet Java numit imageProcessor care contine o clasa numita MyImage. Clasa contine toate metodele
necesare initializarii si modificarii valorilor dintr-o matrice de pixeli de dimensiune m x n. Fiecare pixel este o instanta a
unei alte clase numita Pixel (inclusa de asemenea in pachet) care contine 3 variabile intregi R, G si B care pot avea valori
intre 0 si 255.
Clasa MyImage mai contine metode pentru:
- eliminarea pixelilor care au componentele RGB sub anumite valori primite ca parametri
- eliminarea componentelor R G sau B din toti pixelii
- transformarea valorilor pixelilor in tonuri de gri prin aplicarea formulei 0.21 R + 0.71 G + 0.07 B. Noile componente
R G si B vor fi egale cu noua valoare calculata
Nota: fiecare operatiune este cronometrata.

Importati pachetul intr-o aplicatie Java care instantiaza clasa MyImage. Programul aloca valori aleatoare componentelor
culorilor pixelilor. Aplicati metodele din clasa asupra obiectului creat. Afisati rezultatele si timpii de transformare.

Complexitate ***

8. Creati o aplicație ce verifică numerele de înmatriculare ale mașinilor din România. Formatul acestora este următorul:
[L{L}][NN{N}][LLL], unde L reprezintă o literă, N o cifră, iar acoladele semnifică faptul că pentru București numărul e
format dintr-o singură literă în primul grup, iar grupul de cifre poate să aibă 3 cifre. Implementați metoda de verificare a
numerelor de mașină și aruncați excepții (instante ale unei clase proprii de tip exceptie) specifice fiecărei erori ce poate
să apară la verificare (mesaje particularizate). De exemplu, dacă județul e compus din 2 litere, setul de cifre nu poate să
aibă dimensiunea 3. Ultimele litere nu pot să conțină ”I” și ”O” pe prima și ultima poziție.

9. Definiți o clasă numită Pozitie care controlează poziția unui punct in spațiu (denumire punct (String), coordonatele pe
axele X, Y, Z (valori intregi), constructori, accesori, mutatori). Se declară un tablou de maxim 3 obiecte de tip Pozitie după
care utilizatorul este solicitat să introducă numărul dorit de obiecte. În secvența de initializare a datelor prin citire de la
tastatură se tratează excepția de tip ArrayIndexOutOfBoundsException dată de introducerea unui număr incorect de
obiecte.
Se testează coordonatele tuturor punctelor introduse, iar dacă oricare dintre acestea sunt prea aproape de un alt punct
cu coordonatele predefinite în program (distanta < valoare definita prin program), se lansează o excepție de tip
PunctPreaAproape. În blocul catch aferent utilizatorul este solicitat să reintroducă repetitiv coordonatele obiectului până
când datele furnizate corespund criteriului.

10. Fie un pachet de clase și interfețe Java denumit dbInteraction ce permite interacțiunea cu o bază de date pe baza
autentificării unui utilizator. Pachetul conține următoarele componente:
- o clasă ce definește obiecte de tip Person și care au atributele private nume, prenume, adresă de e-mail, userID și parolă,
alături de metodele accesor și mutator corespunzătoare.
- o interfață pentru autentificare cu metodele createUser( ), deleteUser( ) și login( ). Metodele au ca parametru de intrare
un obiect de tip Person si returnează un șir de variabile de tip Person. Pentru login( ) se definește în interfață o listă de
utilizatori default: admin, dbAdmin și superUser.
- o clasă abstractă VerifyPerson ce extinde clasa Person și implementează metode de verificare a formatelor pentru nume,
prenume, adresă de e-mail, userID și parolă după următoarele specificații:
* numele și prenumele nu pot să conțină alte simboluri decât cele alfabetice
* lungimea numelui și a prenumelui nu poate să fie mai mare de 50 de caractere
* adresa de e-mail trebuie să fie de forma: [a-zA-Z._]@[a-zA-Z.].[a-zA-Z]{2-5}
- clasa abstractă declara, dar nu implementează metodele de verificare a userID și parola.

Creați o aplicație ce interacționează cu acest pachet astfel:


- scrieți o clasă ce implementează interfata de autentificare și care actualizează lista de persoane conform cu acțiunea
specificată.
- scrieți clasa care extinde clasa abstractă Verify și implementează metodele verificare a userID și a parolei după
următoarele specificații:
* userID poate să conțină doar litere, cifre și simbolul “.”
* parola trebuie să aibă lungimea minimă de 8 caractere, cel puțin un caracter uppercase și un simbol non-alfanumeric
- scrieți o clasă de test ce verifică toate funcționalitățile aplicației.

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