Transcript Aplicatia 1

Java – Metode abstracte si
exceptii
abstract


clase
metode
Exceptii



descriere
tratare
generare
Modificatorul abstract



cuvantul cheie abstract poate fi utilizat ca si modificator
aplicat unei clase sau metode;
clasele abstracte nu pot fi instantiate, ele obliga la
implementarea de subclase;
o clasa se declara abstracta daca:





contine cel putin o metoda abstracta;
mosteneste metode abstracte care nu sunt implementate;
cand o clasa declara implementarea unei interfete dar nu
implementeaza toate metodele din interfata.
o metoda abstracta este o metoda declarata, dar
neimplementata, adica nu are cod sau corp;
prima subclasa concreta (neabstracta) trebuie sa
implementeze toate metodele abstracte ale superclasei.
Exceptii




orice program are un
scop, exceptiile sunt
situatii anormale in
rularea lui;
exceptiile trebuie prinse
sau declarate si se
reprezinta ca si obiecte;
orice exceptie are un
anumit tip;
orice exceptie trebuie
prinsa si tratata altfel
programul se termina cu
un mesaj de eroare;
try {
//cod care poate genera erori
}
catch(tipexceptie1 ob) {
//rutină pentru tratarea excepţiei 1
}
catch(tipexceptie2 ob) {
//rutină pentru tratarea excepţiei 2
}
. . .
finally {
//cod de executat înainte de terminarea
// blocului try
}
Aplicatia 1






se pune problema scrierii unei aplicatii ce sa poate calcula, afisa si
reprezenta grafic valorile unei functii date de programator si a primei
derivate;
algoritmul de calcul trebuie sa fie independent de functia aleasa de
programator; din acest motiv clasa de baza ce implementeaza cerintele
este una abstracta, functia devine cunoscuta, adica implementata, doar
in subclasa concreta;
calculul functiei sau a derivatei pot conduce la situatii exceptionale ce
trebuie fie evitate fie tratate.
clasa abstracta se numeste: FunctieA
subclasele concrete se numesc: Functie1 si Functie2
partea de calcul si de afisare folosesc facilitatea de polimorfism in clasa
de testare numita TestFunctii unde tabloul fA (de elemente clasei de
baza) stocheaza referinte la obiectele f1 si f2 (subclase concrete).
Aplicatia 1 / 1
Aceasta clasa abstracta declara functia abstracta de reprezentat cu linia
ingrosata. Ea trebuie implementata in subclasele concrete derivate.
public abstract class FunctieA {
double a, b, h, x;
int i, n;
final int LY = 70;
double[] xf;
double[] yf;
double[] dyf;
public FunctieA(double a, double b, int n) {
this.a = a;
this.b = b;
this.n = n;
h = (b - a) / (n - 1);
xf = new double[n];
yf = new double[n];
dyf = new double[n];
double min(double[] a) {
double m = a[0];
for (int i = 1; i < a.length; ++i)
if (a[i] < m)
m = a[i];
return m;
}
double max(double[] a) {
double m = a[0];
for (int i = 1; i < a.length; ++i)
if (a[i] > m)
m = a[i];
return m;
}
String functip(int p, char c, String in) {
String aux = "";
calcul();
for (int i = 0; i < in.length(); ++i)
if (i == p)
aux += c;
else
aux += in.charAt(i);
return aux;
}
public abstract double functie(double x);
double functied1(double x) {
final double h = 0.001;
return (functie(x + h) - functie(x)) / h;
}
}
Aplicatia 1 / 2
Exceptiile pot sa apara in metoda, ingrosata, calcul() unde functia sau derivata
pot sa nu exista in spatiul valorilor reale (double)
double scale(double v, double vmin, double vmax) {
return (v - vmin) / (vmax - vmin);
}
void calcul() {
for (i = 1; i <= n; ++i) {
x = a + (i - 1) * h;
xf[i - 1] = x;
yf[i - 1] = functie(x);
dyf[i - 1] = functied1(x);
}
}
void afisare() {
String tip;
double minyf = min(yf);
double maxyf = max(yf);
double mindyf = min(dyf);
double maxdyf = max(dyf);
//minimul
//maximul
double ma
double mi
dintre cele 2 minime si
dintre cele 2 maxime
= (maxyf > maxdyf) ? maxyf : maxdyf;
= (minyf < mindyf) ? minyf : mindyf;
System.out.println("----------------------------------------------");
System.out.println("| i |
x
|
f(x)
|
fd1(x) |");
System.out.println("----------------------------------------------");
Aplicatia 1 / 3
for (i = 0; i < n; ++i) {
int pos = (int)(scale(yf[i], mi, ma) * (LY - 1));
int pos0 = (int)(scale(0., mi, ma) * (LY - 1));
int posd = (int)(scale(dyf[i], mi, ma) * (LY - 1));
String tipinit = "";
for (int i = 1; i <= LY; ++i)
tipinit += " ";
//trasare axa Ox
if (ma * mi < 0.)
tip = functip(pos0, '|', tipinit);
else
tip = tipinit;
//F pt. functie
//D pt. derivata
tip = functip(pos, 'F', tip);
tip = functip(posd, 'D', tip);
System.out.printf("| %3d | %-+10.6f | %10.6f | %10.6f | %s\n", i, xf[i], yf[i], dyf[i], tip);
}
System.out.println("----------------------------------------------");
}
}
Aplicatia 1 /4
Aici este dat codul subclaselor concrete si al celei de testare.
public class Functie1 extends FunctieA {
public Functie1(double a, double b, int n) {
super(a,b,n);
}
@Override
public double functie(double x) {
return Math.sin(x)*Math.cos(x/2.) ;
}
}
public class Functie2 extends FunctieA {
public Functie2(double a, double b, int n) {
super(a,b,n);
}
@Override
public double functie(double x) {
return Math.sin(x)/x;
}
}
public class TestFunctii {
public static void main(String[] args) {
Functie1 f1 = new Functie1(-3.,3.,30);
Functie2 f2 = new Functie2(-7.,7.,30);
FunctieA fA[]= new FunctieA[2] ;
fA[0]=f1;
fA[1]=f2;
for(FunctieA f: fA)
f.afisare();
}
}
Aplicatia 1 / 5
Functie1 f1 = new Functie1(-3.,3.,20);
Functie2 f2 = new Functie2(-7.,7.,20);
Aplicatia 1 / 6
Functie1 f1 = new Functie1(-3.,3.,20);
Functie2 f2 = new Functie2(-7.,7.,15);
In aceasta situatie f2=
sin(x)/x pentru x=0 nu
se poate calcula.
Aplicatia in locul valorilor
normale afiseaza NaN.
Aplicatia 1 / 7
daca codul de calcul este rescris sub forma:

void calcul() {
double aux;
for (i = 1; i <= n; ++i) {
x = a + (i - 1) * h;
xf[j - 1] = x;
aux = functie(x);
if (Double.isInfinite(aux) || Double.isNaN(aux))
throw new ArithmeticException("Probleme in evaluare la: " + x);
yf[i - 1] = aux;
dyf[i - 1] = functied1(x);
}
}
atunci se obtine
o exceptie clara la
in situatia de 0/0 si
aplicatia se opreste.

Aplicatia 1 / 8



Java implementeaza
standardul IEEE 754 in lucrul
cu numerele in virgula
flotanta;
conform acestui standard
situatiile de 0/0, nr/0 sunt
permise (nu sunt exceptii) si
au valorile speciale de NaN
sau +/- Infinit motiv pentru
care utilizarea lui try cu
catch nu rezolva aparitia
acestor situatii;
aceste cazuri trebuie testate
in cod cu Double.isNaN() si
Double.isInfinite() apoi luate
masurile necsare de corectie
dupa cum se face in varianta
de calcul() alaturata.
void calcul() {
double aux;
int j=1;
for (i = 1; i <= n; ++i) {
x = a + (i - 1) * h;
xf[j - 1] = x;
aux = functie(x);
if (Double.isInfinite(aux) || Double.isNaN(aux)) {
--n;
continue;
}
yf[j - 1] = aux;
dyf[j - 1] = functied1(x);
++j;
}
}
Aplicatia 2 - try, catch, throw,
throws
Aplicaţia ce urmează este formată din 2 clase Functie.java şi TestExceptii.java.
Ea trebuie să evalueze valoarea unei funcţii F(x) definită în metoda F din clasa
Functie.
x
F(x) 
,
x2
4.5x,
sin(x)
,
x
x<1
1
x
5
x>5
Această metodă generează excepţie de tipul ArithmeticException. Excepţiile
sunt generate deoarece pentru x = -2 expresia x/(x+2) nu se poate calcula, iar
pentru x ∈ (4.5, 5] radicalul are argumentul negativ. Metoda citeste_real() se
foloseşte pentru a citi o valoare numerică reală (sau întreagă) de la tastatură.
Reluarea citirii se face de cel mult 3 ori, după care aplicaţia se opreşte
deoarece se generează o eroare ca nu este prinsă în aplicaţie. În această
situaţie aplicaţie afişează starea stivei pentru a putea determina precis linia şi
codul în care a apărut eroarea.
Aplicatia 2 /1
import java.util.*;
public class Functie {
public double F(double x) throws ArithmeticException{
if (x < 1.) {
if (x == -2.)
throw new ArithmeticException("Impartire cu 0");
return x/(x+2);
}
else if (x <= 5.) {
if (x > 4.5)
throw new ArithmeticException("Argument radical negativ.");
return Math.sqrt(4.5-x);
}
else
return Math.sin(x)/x;
}
public double citeste_real() throws InputMismatchException
{
Scanner in = null;
int contorErr = 0; //contor erori, pt. 3 aplicatia se opreste.
double x;
while(true) {
in = new Scanner(System.in);
try {
x = in.nextDouble();
break; //daca nu sunt erori se iese din ciclu
}
catch (InputMismatchException e) {
++contorErr;
System.out.printf("Eroare(%d) la citire, introduce o valoarea reala.\n", contorErr);
if ( contorErr == 3 )
throw new InputMismatchException("*** Prea prost ca sa bage 1 numar real. ***");
}
}
return x;
}
}
Aplicatia 2 /2
public class TestExceptii {
public static void main(String[] args) {
Functie F1 = new Functie();
double x1, x2;
System.out.print("x1=");
x1 = F1.citeste_real();
System.out.print("x2=");
x2 = F1.citeste_real();
for(double x=x1;x<=x2;++x) {
try {
System.out.printf("%6.3f %10.7f\n",x, F1.F(x));
}
catch (ArithmeticException e) {
System.out.printf("%6.3f %s\n",x, e);
}
}
}
}
Se poate observa cum aplicaţia, deşi întâlneşte situaţii excepţionale, nu se
termină brusc şi abrupt, ci ca urmare a tratării acestora, ajunge să se termine
normal.
Aplicatia 3 – extindere clasa
Exception
Aplicaţia care urmează prezintă modul în care se extinde clasă Exception la
clasa ExceptiiAritmetice.
public class ExceptiiAritmetice extends Exception{
private String mesaj;
public ExceptiiAritmetice(String m) {
super(m);
mesaj = m;
}
public String toString() {
return "\nExceptie: " + mesaj;
}
}
Aplicatia 3/1
public class TestEx2 {
public static int cat(int a, int b) throws ExceptiiAritmetice {
if (b == 0) throw new ExceptiiAritmetice("Imparire cu zero!");
return a / b;
}
public static void main(String[] args) {
int a, b, c;
a=1;
b=0;
System.out.print(a + "/" + b );
try {
c = (int)cat(a,b);
System.out.println( "=" + c );
}
catch (ExceptiiAritmetice e) {
System.out.println(e);
}
}
}
Bibliografie


http://www.east.utcluj.ro/mb/mep/antal/downloads.html > Java: course,
IDE (JDeveloper), JDK and JRE, JDeveloper labs.
http://docs.oracle.com/cd/E18941_01/tutorials/jdtut_11r2_50/jdtut_11r2
_50.html > Getting Started With the JDeveloper IDE