Documente Academic
Documente Profesional
Documente Cultură
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 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.
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
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
}
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).
Î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.
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 : 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;
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.
- ce trebuie să fie adevărat în momentul apelului unei metode sau după apelul acesteia
Exemple
import java.util.Scanner;
Scanner scanner;
public KeyboardReader(){
scanner = new Scanner(System.in);
}
return rez;
}
class Test {
int a = reader.readInt();
System.out.println("Valoarea citita: " + a);
reader.close();
}
}
return rez;
}
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);
}
}
}
class Test {
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.");
}
}
}
import java.lang.Throwable;
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");
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;
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.