Aplicatii Matematice In Java

CUPRINS

CAPITOLUL 1: GENERALITĂȚI

1.1. INTRODUCERE ÎN LIMBAJUL DE PROGRAMARE JAVA

1.2. ELEMENTE JAVA FOLOSITE ÎN DEZVOLTAREA APLICAȚIEI

JAVA SOCKETS

JAVA THREAD

DESENAREA ÎN JAVA

Pachetele AWT și SWING

1.2.4.1 FERESTRE ȘI BUTOANE

CAPITOLUL 2: PREGĂTIREA MEDIULUI DE LUCRU

2.1. INSTALARE JAVA JRE, NETBEANS ȘI JDK

2.2. PREZENTAREA MEDIULUI INTEGRAT NETBEANS

Exemplu de creare a unei aplicaȚii Java

CAPITOLUL 3: DESCRIEREA APLICAȚIEI

3.1.STRUCTURA APLICAȚIEI

3.2.APLICAȚII MATEMATICE ÎN JAVA

3.2.1 COMBINATORICĂ

3.2.2 ECUAȚII

CAPITOLUL 1: GENERALITAȚI

Introducere în limbajul de programare Java

Ce este JAVA ?

Java este un limbaj de programare orientat-obiect, puternic tipizat, conceput de către James Gosling la Sun Microsystems (acum filială Oracle) la începutul anilor ʼ90, fiind lansat în 1995. Cele mai multe aplicații distribuite sunt scrise în Java, iar noile evoluții tehnologice permit utilizarea sa și pe dispozitive mobile gen telefon, agenda electronică, palmtop etc. În felul acesta se creează o platformă unică, la nivelul programatorului, deasupra unui mediu eterogen extrem de diversificat. Acesta este utilizat în prezent cu succes și pentru programarea aplicațiilor destinate intranet-urilor[1].

Limbajul împrumută o mare parte din sintaxă de la C și C++, dar are un model al obiectelor mai simplu și prezintă mai puține facilități de nivel jos. Un program Java compilat, corect scris, poate fi rulat fără modificări pe orice platformă care are instalată o mașină virtuală Java (engleză Java Virtual Machine, prescurtat JVM). Acest nivel de portabilitate (inexistent pentru limbaje mai vechi cum ar fi C) este posibil deoarece sursele Java sunt compilate într-un format standard numit cod de octeți (engleză byte-code) care este intermediar între codul mașină (dependent de tipul calculatorului) și codul sursă.

Mașina virtuală Java este mediul în care se execută programele Java. În prezent, există mai mulți furnizori de JVM, printre care Oracle, IBM, Bea, FSF. În 2006, Sun a anunțat că face disponibilă varianta sa de JVM ca open-source.

Există 4 platforme Java furnizate de Oracle:

Java Card – pentru smartcard-uri (carduri cu cip)

Java Platform, Micro Edition (Java ME) — pentru hardware cu resurse limitate, gen PDA sau telefoane mobile,

Java Platform, Standard Edition (Java SE) — pentru sisteme gen workstation, este ceea ce se găsește pe PC-uri,

Java Platform, Enterprise Edition (Java EE) — pentru sisteme de calcul mari, eventual distribuite.

Java : un limbaj compilat și interpretat

În funcție de modul de execuție al programelor, limbajele de programare se împart în două categorii :

interpretate : instrucțiunile sunt citite linie cu linie de un program numit interpretor și traduse în instrucțiuni mașină; avantaj : simplitate; dezavantaje : viteza de execuție redusă

compilate : codul sursă al programelor este transformat de compilator într-un cod ce poate fi executat direct de procesor; avantaj : execuție rapidă; dezavantaj : lipsa portabilitații, codul compilat într-un format de nivel scazut nu poate fi rulat decât pe platforma pe care a fost compilat.

Programele Java pot fi atât interpretate cât și compilate.

Cod sursa Java (compilare) Cod de octeți

Codul de octeți este diferit de codul mașină. Codul mașină este reprezentat de o succesiune de 0 si 1; codurile de octeți sunt seturi de instrucțiuni care seamănă cu codul scris în limbaj de asamblare.

Codul mașină este executat direct de către procesor și poate fi folosit numai pe platforma pe care a fost creat; codul de octeți este interpretat de mediul Java și de aceea poate fi rulat pe orice platformă care folosește mediul de execuție Java neutralitatea limbajului Java din punct de vedere arhitectural.

Cum este rulat un program Java ? Interpretorul Java transformă codul de octeți într-un set de instrucțiuni mașină, întârzierea interpretarii fiind însă foarte mică datorită asemănării dintre codul de octeți și limbajul de asamblare și din acest motiv execuția se face aproape la fel de repede ca în cazul programelor compilate.

Cum este obținută neutralitatea arhitecturală a limbajului Java ? Cu alte cuvinte, cum este posibilă portarea codului de octeți pe calculatoare diferite? Truc : codul sursă este compilat nu pentru calculatorul pe care se lucrează ci pentru un calculator inexistent, acest calculator imaginar fiind numit Mașina virtuală Java (Java Virtual Machine). Interpretorul acționează apoi ca un intermediar între Masina virtuala Java si mașina reală pe care este rulat programul.

Java și conceptele programării orientate pe obiecte

Limbajul Java este următorul pas logic în domeniul limbajelor de programare și se bazează pe cel mai popular limbaj de programare al momentului C++. În Java se pot obține programe cu aspectul și comportarea programelor C++, dar beneficiind de avantajele oferite de un limbaj proiectat special pentru POO. Java renunță complet la programarea procedurală specifică C-ului și obligă la folosirea conceptelor solide ale POO.

Conceptele programării orientate pe obiecte cuprind :

Obiectele :

unitatea elementară a POO

starea obiectului este dată de variabile de instant

comportamentul obiectului este dat de metode

ușor de refolosit, actualizat, întretinut

Încapsularea și transmiterea de mesaje

Clasele

încapsulează obiecte

o singură clasă poate fi folosită pentru instanțierea mai multor obiecte

Bibliotecile (numite pachete, în Java, reprezintă colecție de clase înrudite )

Moștenirea: permite

extinderea funcționalității unor clase existente

refolosirea codului

Modificatorii de acces: controlează accesul la metodele și variabilele obiectelor

Acestea pot fi :

Private – accesibile doar obiectelor din aceeași clasă

Protejate – accesibile obiectelor din aceeași clasă și din subclasele clasei respective

Prietenoase – (nivelul de accesibilitate prestabilit) accesibile tuturor claselor din pachetul curent

Publice – accesibile tuturor claselor din orice pachet

Programarea în limbajul Java. Caracteristicile de bază al limbajului Java

Folosirea în medii de rețea distribuite

Java a fost proiectat pentru un mediu complex cum este Internetul și de aceea trebuie să poată rula pe platforme eterogene distribuite. Acest lucru este posibil deoarece :

este neutru din punct de vedere arhitectural = programele pot fi rulate pe orice platformă care are instalat mediul Java

are un grad ridicat de portabilitate = conține obiecte care pot fi folosite pe platforme eterogene și respectă standardele IEEE (Institute of Electrical and Electronics Engineers) pentru structurile de date (folosirea întregilor, a numerelor în virgulă mobilă, a șirurilor, etc)

este distribuit = poate folosi atât obiecte memorate local cât și obiecte stocate pe calculatoare aflate la distanță

este compatibil cu mediile de lucru în rețea (poate fi utilizat în rețele complexe) și acceptă direct protocoale de rețea obișnuite cum ar fi FTP și HTTP

Asigurarea performanței ridicate

compilatorul și sistemul de execuție oferă o viteză ridicată rulării programelor

are încorporate posibilități de execuție multifilară (rularea simultană a mai multor procese) folosind un sistem de acordare de priorități proceselor ce trebuie executate. Printre procesele care rulează în fundal sunt cele de “colectare a gunoiului” și de gestionare a memoriei.

Refolosirea codului și fiabilitatea

Java este un limbaj dinamic, lucru asigurat prin întârzierea legării obiectelor și legarea dinamică a claselor în timpul execuției, ceea ce împiedică apariția erorilor în cazul schimbării mediului de lucru dupa compilarea programului sursă.

Fiabilitatea este asigurată prin eliminarea pointerilor, prin folosirea verificării dinamice a limitelor și prin gestionarea automată a memoriei, înlăturându-se posibilitatea fisurilor și violărilor de memorie. O altă cale de evitare a erorilor este verificarea structurilor de date atât la compilare cât și în timpul executiei.

Asigurarea securității

Interzice accesul la stiva sistemului, la zona liberă de memorie și la secțiunile protejate de memorie

Verifică validitatea codului semnalând urmatoarele:

Violările de acces

Conversiile ilegale de date

Valori și parametri incorecți

Modificarea claselor sau folosirea incorectă a acestora

Depășirea stivei în partea superioară sau inferioară

Activități suspecte sau neautorizate

Structura lexicală Java

Setul de caractere

Limbajul Java lucrează în mod nativ folosind setul de caractere Unicode. Acesta este un standard internațional care înlocuiește vechiul set de caractere ASCII. Motivul acestei înlocuiri a fost necesitatea de a reprezenta mai mult de 256 de caractere. Setul de caractere Unicode fiind reprezentat pe 16 biți are posibilități mult mai mari.

Vechiul standard ASCII este însă un subset al setului Unicode, ceea ce înseamnă că se vor regăsi caracterele ASCII cu exact aceleași coduri ca și mai înainte în noul standard.

Java folosește setul Unicode în timpul rulării aplicațiilor ca și în timpul compilării acestora. Folosirea Unicode în timpul execuției nu înseamnă nimic altceva decât faptul că o variabilă Java de tip caracter este reprezentată pe 16 biți iar un șir de caractere va ocupa fizic în memorie de două ori mai mulți octeți decât numărul caracterelor care formează șirul.

În ceea ce privește folosirea Unicode în timpul compilării, compilatorul Java acceptă la intrare fișiere sursă care pot conține orice caractere Unicode. Se poate lucra și cu fișiere ASCII obișnuite în care se pot introduce caractere Unicode folosind secvențe escape. Fișierele sursă sunt fișiere care conțin declarații și instrucțiuni Java. Aceste fișiere trec prin trei pași distincți la citirea lor de către compilator:

Șirul de caractere Unicode sau ASCII, memorat în fișierul sursă, este transformat într-un șir de caractere Unicode. Caracterele Unicode pot fi introduse și ca secvențe escape folosind doar caractere ASCII.

Șirul de caractere Unicode este transformat într-un șir de caractere în care sunt evidențiate separat caracterele de intrare față de caracterele de sfârșit de linie.

Șirul de caractere de intrare și de sfârșit de linie este transformat într-un șir de cuvinte ale limbajului Java.

În primul pas al citirii fișierului sursă, sunt generate secvențe escape. Secvențele escape sunt secvențe de caractere ASCII care încep cu caracterul backslash \. Pentru secvențele escape Unicode, al doilea caracter din secvență trebuie să fie u sau U. Orice alt caracter care urmează după backslash va fi considerat ca fiind caracter nativ Unicode și lăsat nealterat. Dacă al doilea caracter din secvența escape este u, următoarele patru caractere ASCII sunt tratate ca și cifre hexazecimale (în baza 16) care formează împreună doi octeți de memorie care reprezintă un caracter Unicode.

Se pot folosi la intrare și fișiere ASCII normale, pentru că ASCII este un subset al Unicode. De exemplu, se poate scrie:

int f\u0660 = 3;

Numele variabilei are două caractere și al doilea caracter este o cifră arabic-indic.

Exemple de secvențe Unicode:

\uaa08 \U0045 \uu6abe

În al doilea pas al citirii fișierului sursă, sunt recunoscute ca și caractere de sfârșit de linie caracterele ASCII CR și ASCII LF. În același timp, secvența de caractere ASCII CR-ASCII LF este tratată ca un singur sfârșit de linie și nu două. În acest mod, Java suportă în comun standardele de terminare a liniilor folosite de diferite sisteme de operare: MacOS, Unix și DOS.

Este important să se separe caracterele de sfârșit de linie de restul caracterelor de intrare pentru a ști unde se termină comentariile de o singură linie (care încep cu secvența //) precum și pentru a raporta odată cu erorile de compilare și linia din fișierul sursă în care au apărut acestea.

În pasul al treilea al citirii fișierului sursă, sunt izolate elementele de intrare ale limbajului Java, și anume: spații, comentarii și unități lexicale.

Spațiile pot fi caracterele ASCII SP (spațiu), FF (avans de pagină) sau HT (tab orizontal) precum și orice caracter terminator de linie.

Unități lexicale

Unitățile lexicale sunt elementele de bază cu care se construiește semantica programelor Java. În șirul de cuvinte de intrare, unitățile lexicale sunt separate între ele prin comentarii și spații. Unitățile lexicale în limbajul Java pot fi:

Cuvinte cheie

Cuvintele cheie sunt secvențe de caractere ASCII rezervate de limbaj pentru uzul propriu. Cu ajutorul lor, Java își definește unitățile sintactice de bază. Nici un program nu poate să utilizeze aceste secvențe altfel decât în modul în care sunt definite de limbaj. Singura excepție este aceea că nu există nici o restricționare a apariției cuvintelor cheie în șiruri de caractere sau comentarii.

Cuvintele cheie ale limbajului Java sunt:

Identificatori

Identificatorii Java sunt secvențe nelimitate de litere și cifre Unicode, începând cu o literă. Identificatorii nu au voie să fie identici cu cuvintele rezervate. Un caracter Unicode este o literă dacă este în următoarele intervale și nu este cifră:

Tabelul 1.1 Literele Unicode

Literali

Un literal este modalitatea de bază de exprimare în fișierul sursă a valorilor pe care le pot lua tipurile primitive și tipul șir de caractere. Cu ajutorul literalilor se pot introduce valori constante în variabilele de tip primitiv sau în variabilele de tip șir de caractere.

În limbajul Java există următoarele tipuri de literali:

literali întregi

literali flotanți

literali booleeni

literali caracter

literali șir de caractere

Separatori

Un separator este un caracter care indică sfârșitul unei unități lexicale și începutul alteia. Separatorii sunt necesari atunci când unități lexicale diferite sunt scrise fără spații între ele. Acestea se pot totuși separa dacă unele dintre ele conțin caractere separatori. În Java separatorii sunt următorii:

( ) { } [ ] ; , .

Exemple de separare:

a[i]sin(56)

În primul exemplu nu este o singură unitate lexicală ci patru: a, [, i, ]. Separatorii [ și ] dau această informație. În al doilea exemplu, unitățile lexicale sunt tot 4 sin, (, 56, ).

Atenție, separatorii participă în același timp și la construcția sintaxei limbajului. Ei nu sunt identici cu spațiile deși, ca și acestea, separă unități lexicale diferite.

Operatori – simboluri grafice pentru operațiile elementare definite de limbajul Java.

Elemente Java folosite în dezvoltarea aplicației

1.2.1.Java Sockets

O rețea este formată dintr-o mulțime de calculatoare și periferice (imprimante, plotere, scannere, modemuri etc.) conectate între ele.

Un sistem distribuit este o colecție de calculatoare și/sau procesoare autonome (având o unitate de comandă proprie), interconectate (capabile de a schimba informații între ele). Elementele colecției poartă numele de noduri. Un astfel de sistem poate fi programat pentru a rezolva probleme de concurență și de paralelism.

Sistemele distribuite au apărut ca o necesitate pentru:

– schimbul de informații între noduri;

– partajarea unor resurse (printere, memorie backup, unități de disc etc.);

– siguranța în funcționare: dacă un nod "cade", întregul sistem trebuie (dacă este posibil) să fie capabil să asigure în continuare funcționarea, prin redirijarea (rutarea) mesajelor prin nodurile funcționale.

Tipuri de rețele

O primă clasificare a rețelelor este constituită de împărțirea lor în rețele LAN (Local Area Network) și rețele WAN (Wide Area Network).

Rețelele LAN sunt folosite de obicei pentru a partaja resurse (fișiere și periferice) și de a facilita schimbul de informații între nodurile componente. Conectarea tipică este realizată prin cablu, cu o limită dată pentru un drum între două noduri (de exemplu 10 km).

La fiecare moment de timp, într-o astfel de rețea este transmis un singur mesaj.

Numele rețelei desemnează produsul și nu rețeaua (așa cum se întâmplă la rețelele WAN). De exemplu Ethernet este un produs al companiei XEROX.

Probleme algoritmice pentru astfel de rețele:

1) sincronizarea: așteptarea îndeplinirii unei condiții;

2) difuzarea totală (broadcasting) : transmiterea unui mesaj către toate celelalte noduri;

3) selectarea unui proces pentru îndeplinirea anumitor acțiuni;

4) detectarea terminării: un nod ce întreprinde o acțiune, în care antrenează și alte noduri, trebuie să fie capabil să detecteze momentul încheierii acțiunii;

5) excluderea reciprocă: utilizarea unor resurse sub excludere reciprocă (de exemplu modificarea unui fișier sau scrierea la imprimantă);

6) detectarea și prevenirea blocării totale (deadlock);

7) gestionarea distribuită a fișierelor.

Rețelele WAN permit comunicarea pe distanțe mai mari, prin legături directe între noduri, realizate prin linie telefonică, fibră optică, legătură via satelit etc. Ele sunt grafuri orientate.

Probleme algoritmice pentru astfel de rețele:

1) siguranța schimbului de informații pe fiecare arc al grafului. Informația eronată trebuie recunoscută ca atare și corectată. Este posibil ca mesajele să sosească într-un nod în altă ordine decât cea în care au fost transmise, pot fi duplicate etc.;

2) selectarea de căi de comunicare (rutare) între nodurile care schimbă informații, deoarece un graf complet este prea costisitor și în general nici nu este realizabil. Modul de rutare trebuie actualizat în cazul în care un nod al rețelei cade (devine nefuncțional);

3) evitarea congestionării unor căi de comunicație, realizată tot prin (re)rutare;

4) evitarea blocării totale;

5) securizarea datelor și a transmisiilor.

Deosebirile esențiale între cele două tipuri de rețele se referă la:

1) securizare: în rețele LAN se presupune că transmiterea este corectă, pe când în rețelele WAN trebuie presupus că în timpul transmiterii mesajelor se poate întâmpla "ceva rău";

2) timpul de comunicare: în rețelele WAN timpul de comunicare este mult mai mare (de 10k ori mai mare, k 1) decât în rețelele LAN; acest timp este la rândul său mult mai mare decât cel cerut de prelucrările locale;

3) omogenitatea: în rețelele WAN trebuie presupus că sunt utilizate simultan mai multe protocoale, ceea ce pune problema recunoașterii și conversiei între ele;

4) încrederea reciprocă: nu este presupusă în rețelele WAN și drept urmare trebuie luate măsuri de securitate adecvate.

Protocoale

Comunicarea între componentele unei rețele (respectiv unui sistem distribuit) se face prin mulțimi de reguli, numite generic protocoale.

Un protocol cuprinde atât formatul mesajului ce este efectiv transmis, cât și modul în care trebuie răspuns la mesajul respectiv.

Protocolul folosit pe Internet este IP (Internet Protocol). Mesajele circulă în pachete, ce pot fi:

– pachete Internet, pentru care protocolul este TCP (Transmission Control Protocol);

– datagrame, pentru care protocolul este UDP (User Datagram Protocol);

Internetul folosește nume (adrese) simbolice pentru rețele și pentru mașinile gazdă; ele se mai numesc nume de domeniu. Lor li se asociază în mod biunivoc adrese (numerice) IP, folosite efectiv la comunicarea între nodurile rețelei. Asocierea cade în sarcina unui sistem de nume de domeniu (DNS = Domain Name System).

O adresă numerică IP are foma:

a.b.c.d unde a, b, c, d sunt numere naturale din mulțimea {0, 1, …, 255}.

Modelul Client/Server

Comunicarea între nodurile unei rețele constă în transmiterea (recepționarea) de pachete către (de la) gazde ale aceleași rețele sau ale unei alte rețele.

Modelul utilizat pe scară largă în sistemele distribuite (și care va fi cel folosit în continuare) este sistemul Client/Server. În acest model există:

– o mulțime de procese Server, fiecare jucând rolul de gestionar de resurse pentru o colecție de resurse de un anumit tip;

– o mulțime de procese Client; fiecare execută activități care necesită acces la resurse hard/soft disponibile (partajate) de servere.

Un gestionar de resurse poate avea și el nevoie de resurse gestionate de un alt proces Server. Drept urmare, unele procese pot fi atât de tip Client, cât și de tip Server , insă doar serverele gestionează resurse.

Serverele sunt cele care își încep primele activitatea. În mod tipic, un server oferă succesiv clienților posibilitatea de a se conecta la el (spunem că acceptă conexiuni de la clienți). La început clientul își manifestă dorința de a se conecta și, dacă serverul este gata să accepte conexiunea, aceasta se realizează efectiv; este vorba deci de o acțiune de la client către server. Apoi transmisia informațiilor devine bidirecțională, fluxul de informații putând circula acum în ambele sensuri.

Teoretic, activitatea unui server se desfășoară la infinit.

Pentru conectare la server, clientul trebuie să cunoască adresa serverului (fie cea numerică, fie cea simbolică), precum și numele portului pus la dispoziție de server. Portul nu este o locație fizică, ci o extensie software corespunzătoare unui serviciu. Serverul poate oferi mai multe servicii, pentru fiecare existând un număr de port. Cele standard sunt:

7 : ping (ecou) 21 : ftp (transfer de fișiere) 23 : telnet

25 : email 79 : finger 80 : Web

110 : POP3 (Post Office Protocol)

Porturile din intervalul 0..1023 sunt în general rezervate pentru servicii speciale (de genul celor de mai sus) și pentru clienți privilegiați.

Clientul inițiază conexiunea prin rețea, specificând adresa serverului și portul prin care dorește să comunice. Serverul trebuie să precizeze numai portul; apoi el trebuie să execute o comandă prin care să anunțe că este gata să accepte conexiuni pe portul respectiv; drept urmare el rămâne în așteptare până când un client dorește să se conecteze și conexiunea este stabilită cu succes. Un server poate accepta conexiuni de la mai mulți clienți: pentru fiecare crează un fir de executare.

Clasa InetAddress

Această clasă, aflată în pachetul java.net, furnizează informații asupra adreselor (simbolică și numerică) unui calculator gazdă.

Clasa nu are constructori publici. Principalele metode sunt:

public static InetAddress getLocalHost (): returnează numele calculatorului gazdă (pe care se află în curs de executare aplicația). Acest nume, convertit la String, are forma: adresă_simbolică/adresă_IP;

public static InetAddress getByName(String s) dându-se ca argument adresa simbolică sau numerică a calculatorului gazdă, metoda întoarce un obiect de tipul InetAddress; metoda poate lansa excepția UnknownHostException;

public String getHostName() întoarce adresa simbolică a calculatorului gazdă;

public byte[] getAddress()întoarce un tablou de 4 octeți, ce compun adresa numerică.

Exemplu: Determinarea adreselor unui calculator și obținerea uneia dintre aceste adrese cunoscând-o pe cealaltă:

Întrebare. "Are sens să studiem facilitățile oferite de Java pentru lucru în rețea dacă avem la dispoziție un singur calculator?". DA! Se pot de exemplu deschide mai multe ferestre de comandă. Adresa IP: numele calculatorului, numele standard "localhost" sau "127.0.0.1".

Comunicare prin socket-uri

Socket-urile sunt folosite pentru transmiterea de date folosind protocolul TCP/IP. Ele sunt obiecte ce trebuie create la ambele capete ale conexiunii. Socket-urile client sunt obiecte de tipul clasei Socket, iar socket-urile server sunt obiecte de tipul clasei ServerSocket; ambele clase fac parte din pachetul java.net. Socket-urilor li se pot atașa un flux de intrare și unul de ieșire, prin care pot recepționa/ transmite, date.

În continuare este prezentată schema generală a lucrului cu socket-uri, apelând la facilitățile de intrare/ieșire la nivel de octet.

Un mod tipic de creare a unui socket client este următorul:

unde adresa este adresa IP a serverului, iar nrport este numărul portului ales pentru comunicare. Socket-ului îi sunt atașate fluxul os ce va fi folosit pentru a transmite date serverului, precum și fluxul is ce va fi folosit pentru recepționarea datelor transmise de server.

Un mod tipic de creare a unui socket server este următorul:

Pentru server nu este necesară precizarea unei adrese IP, ci numai a unui port, care trebuie să coincidă cu cel folosit de client.

Metoda accept: se așteaptă ca un client să încerce să se lege la server; în momentul în care acest lucru se întâmplă și legătura s-a stabilit, metoda crează și întoarce un socket cs de tip client. Acestuia i se atașează un flux de intrare și unul de ieșire.

În final toate socket-urile și fluxurile trebuie închise explicit prin invocarea metodei close.

Clasa URL

Clasa URL este declarată în pachetul java.net prin:

public final class URL extends Object

implements Serializable

Un obiect de tip URL, numit și locație URL, este o referință la o resursă Web. Resursa poate fi un fișier, un director, dar și un obiect mai complex ca de exemplu o cerere către o bază de date sau un motor de căutare. Ca sintaxă, o astfel de adresă cuprinde 4 părți:

protocol:// adresa :port /cale

unde protocol desemnează serviciul exportat de server sau căutat de client (de exemplu http sau ftp), adresa este adresa simbolică sau numerică a mașinii gazdă referite, port portul folosit pentru comunicare, iar cale identifică resursa.

1.2.2. Java Thread

Un sistem multiprocesor (SM) este un mecanism ce permite unui sistem de a folosi mai mult de un procesor. Sistemul Multiprocesor Simetric (SMS) este o parte a Calculului Paralel unde toate procesoarele sunt identice. Într-un SMS, procesoarele sunt dirijate în așa fel încât sarcinile sunt împărțite de către sistemul de operare iar aplicațiile sunt executate pe mai multe procesoare ce împart același spațiu de memorie. SMS garantează că întreg numărul de procesoare deservește sistemul de operare. Fiecare sub-proces poate fi executat pe orice procesor liber. Astfel se poate realiza echilibrarea încarcării între procesoare. Java conține câteva caracteristici care-l fac un limbaj ideal pentru SMS. Este un limbaj orientat obiect foarte simplu și este conceput să suporte programarea multiprocesor.

Multitasking-ul este o metodă prin intermediul căreia mai multe procese utilizează în comun resursele calculatorului (inclusiv procesorul). În situația unui calculator cu un singur procesor, se spune că în orice moment rulează cel mult un proces, ceea ce înseamnă că procesorul execută instrucțiunile unui singur proces la un moment dat. Sarcina alegerii procesului care să se afle în execuție la un moment dat este o problemă de planificare. Operația de a opri un proces aflat în execuție, pentru a-i aloca un timp procesor altui proces aflat în așteptare se numește schimbare de context (context switch). Realizarea frecventă a acestor schimbări de context crează iluzia execuției în paralel a mai multor programe.

În cazul unui calculator cu mai multe procesoare, multitasking-ul permite execuția unui număr de procese mai mare decât numărul de procesoare.

Sistemul de operare este cel care se ocupă de planificarea proceselor, planificare ce se încadrează într-una din următoarele strategii:

în cazul sistemelor cu multiprogramare, procesul curent se află în execuție până în momentul în care realizează o operație ce presupune așteptarea după un eveniment extern (o operație de I/O), sau până când planificatorul de procese forțează eliberarea procesorului.

într-un sistem de tip time-sharing, fiecare process va elibera procesorul în mod voluntar după expirarea cuantei de timp alocate acestuia sau în urma apariției unui eveniment hardware cum ar fi o întrerupere.

în cadrul sistemelor real-time, unui proces aflat în stare de așteptare i se garantează accesul la procesor în cazul apariției unui eveniment extern. Astfel de sisteme sunt proiectate pentru controlul unor dispozitive mecanice cum ar fi roboții industriali.

Comutarea între procese consumă timp procesor pentru ca planificatorul de procese să înghețe starea unui proces și să dezghețe starea altui proces (schimbare de context). Dacă mai multe procese concurente sunt executate pe același procesor și toate execută calcule atunci timpul total de execuție va fi mai mare decât timpul de execuție al unui program secvențial echivalent.

Creșterea vitezei sistemului se poate realiza prin întrețeserea diferitelor faze ale mai multor procese.

În cadrul unui proces se pot identifica două tipuri de faze din punct de vedere logic: faza de calcul și faza de I/O. Faza de calcul se realizează exclusiv la nivelul procesorului utilizându-se la maxim funcțiunile acestuia. Faza de I/O (intrare/ieșire) presupune un aport mai mare din partea perifericelor (imprimante, hard discuri, plăci de rețea, etc), procesul așteptând ca un periferic să-și termine sarcina. În timp ce un proces se află într-o fază de I/O așteptând după finalizarea unei operații de către un dispozitiv periferic, un proces aflat în faza de calcul poate ocupa procesorul.

În cazul multitasking-ului preemtiv planificatorul de procese alocă cuante de timp procesor egale fiecărui proces, asigurându-le astfel un tratament echitabil. De asemenea, sistemul poate răspunde rapid unui eveniment extern (cum ar fi sosirea unor date) ce presupune procesarea de către procesul curent sau de către un altul.

În cazul multitasking-ului non-preemtiv, planificatorul îi dă controlul unui proces până când acesta se termină, sau eliberează singur procesorul.

Ce sunt thread-urile?

Thread-ul reprezintă execuția liniară a unei singure secvențe de instrucțiuni ce rulează în interiorul programului . Toți programatorii sunt familiarizați cu scrierea programelor secvențiale. Programele secvențiale au un punct de start, o secvență de execuție și un punct terminal. Caracteristica cea mai importantă la un program secvențial este aceea ca în orice moment se execută o singură instrucțiune. Thread-ul este similar cu un program secvențial: are și el un punct de start, o secvență de execuție și un punct terminal. De asemenea într-un thread se execută doar o singură instrucțiune la un moment dat. Și totuși un thread nu este la fel ca un program obișnuit.

Spre deosebire de programe, thread-ul nu poate exista de unul singur. Thread-urile coexistă în interiorul unui program. Prin urmare putem avea mai multe thread-uri care se execută simultan.

De ce sa folosim thread-uri?

Un singur thread nu oferă nimic nou. Orice program scris până acum avea cel puțin un thread în interiorul său. Noutatea apare atunci când se vrea folosirea mai multor thread-uri, ceea ce înseamnă că aplicația poate să facă mai multe lucruri în același timp. Fiecare thread poate să facă altceva în același timp: unul să încarce o pagină Web, altul să animeze o icoană sau toate pot colabora la același job (generarea unei imagini 3D). Când se folosește corespunzator multithreading-ul performanțele applet-ului sau a aplicației unde este folosit cresc simțitor.

Multithreading-ul poate simplifica fazele de proiectare și planificare a tuturor sarcinilor greu de implementat într-un program secvențial. Un exemplu de thread-uri este un procesor de text care poate să tipărească o pagină (paginare, încadrare și trimitere către imprimantă) în background. Se poate continua editarea în timp ce pagina este trimisă către imprimantă.

Alt exemplu este acela a unui browser Web care permite defilarea unui text al unei pagini încărcate în timp ce browser-ul se ocupă cu aducerea imaginilor.

Thread-urile pot face calculul mai rapid. Prin segmentarea unui task în subtask-uri și apoi având câte un thread pentru fiecare subtask se poate crește mult viteza de execuție. Această afirmație este general valabilă pentru un SMS. Când se execută două thread-uri, ele vor fi executate simultan, fiecare pe câte un procesor și astfel se realizează o creștere semnificativă a vitezei. Avantaje similare se obțin când se utilizează Java pe alte platforme de calcul paralel și distribuit cum ar fi Sistemele cu Memorie Distribuita (SMD).

Concurenta thread-urilor

Procesoarele calculatoarelor pot executa doar o instrucțiune la un moment dat. De ce se spune că thread-uri diferite se execută în același timp?

Pe o mașină multiprocesor, thread-urile pot exista pe procesoare diferite în același timp fizic, aceasta menținându-se valabil chiar dacă procesoarele sunt pe calculatoare diferite conectate într-o rețea. Și pe o mașină cu un singur procesor, thread-urile pot împărți același procesor, rulând într-o manieră întrețesută, competiția pentru timpii CPU creând iluzia că ele se execută simultan.

Această iluzie pare reală atunci când, de exemplu, 30 de imagini distincte pe secundă captate de ochiul uman sunt percepute într-un flux continuu de imagine. Această comutare între thread-uri are și ea un preț. Consumă timp CPU pentru ca acesta să înghețe starea unui thread și să dezghețe starea unui alt thread (schimbare de context). Dacă thread-urile concurente sunt executate pe același procesor și toate execută calcule atunci timpul total de execuție nu va lua mai mult decât timpul de execuție al unui program secvențial care realizează același lucru.

Din moment ce într-un sistem monoprocesor thread-urile concură la timpul procesor cum este posibilă creșterea vitezei sistemului? Aceasta se realizează prin întrețeserea unor faze diferite ale mai multor thread-uri. Multe task-uri pot fi segmentate logic în tipuri de faze: faza de calcul și faza I/O.

Faza de calcul necesită atenția maximă din partea CPU-ului prin utilizarea unor metode de calcul.

Faza de I/O (intrare/ieșire) necesită atenție maximă din partea perifericelor (imprimante, hard discuri, plăci de retea, etc) și în aceste situații procesorul este în general liber, așteptând ca perifericul să-și termine sarcina. Creșterea vitezei este obținută prin întrețeserea fazelor. În timp ce un thread se află într-o fază de I/O așteptând ca o secvență de date să fie încărcată de pe hard disk, un thread cu o fază de calcul poate ocupa procesorul și când ajunge la o faza I/O, celălalt thread (care tocmai a terminat faza I/O proprie) poate începe să utilizeze CPU-ul.

Contextul thread-urilor si memoria distribuita

Thread-urile rulează în contextul unui program, folosind resursele acestuia. Fiecare thread are propriile variabile și puncte de execuție, dar variabilele globale sunt împărțite de toate thread-urile. Deoarece împart același spațiu (variabilele globale și alte resurse) toate firele de execuție pot accesa la un moment dat aceeași dată. Pentru un programator într-un sistem cu memorie distribuită, împărțirea memoriei este un lucru transparent, realizat la un nivel ascuns al sistemului de operare. Oricum, în cazul unor asemenea sisteme, trebuie avută o atenție sporită pentru minimizarea utilizării concurentă a variabilelor comune de către mai multe thread-uri, deoarece această situație ar putea degenera într-o sufocare a aplicației.

Thread-urile Java sunt implementate de clasa Thread, iar actuala implementare a thread-urilor este realizată de catre sistemul de operare.

În Java, fiecare thread este încapsulat într-o clasă și rulează prin intermediul unor metode specifice în instanța unei clase.

Această instanță nu este o instanță a clasei Thread ci este o instanță a unei clase derivată din clasa Thread sau a unei clase care implementează interfața Runnable (Runnable Interface).

Clasele care instanțiază astfel de obiecte sunt numite "runnable classes" și obiectele sunt numite "runnable objects". Execuția unui thread începe cu apelarea unei metode din clasa Runnable sau dintr-o subclasă a acesteia. Această metodă se execută atâta timp cât ea există și apoi thread-ul moare (aceasta implică faptul că pentru o metodă ce execută o buclă infinită, thread-ul asociat nu moare niciodată).

Un thread poate să fie terminat drept urmare a unui eveniment extern. Limbajul Java oferă două căi pentru crearea firelor de execuție :

Crearea unei clase care extinde clasa Thread din biblioteca de clase java.lang

Crearea unei clase care implementează interfața Runnable din biblioteca de clase java.lang

Clasa Thread de asemenea implementează interfața Runnable.

Exemplul de clasă derivată din clasa Thread suprascrie una din metodele sale – metoda run(). Metoda run() este cea mai importantă deoarece conține codul pe care thread-ul îl va executa. Pentru majoritatea thread-urilor această metodă conține o buclă infinită. Pentru a lansa în execuție metoda run() mai întâi trebuie creată o instanță a acestei clase, apoi se apelează metoda start() ce face thread-ul activ și invocă metoda run().

Secvența de cod anterioară combinată cu clasa TestTread va afișa mesajul "Hello world!" pe ecran. Ce se întâmplă de fapt aici? Metoda main() va porni thread-ul și se va termina; thread-ul nu se va termina însă în acest moment. El va executa metoda run() până când aceasta se termină. Metoda run() va afișa efectiv mesajul "Hello world!" pe ecran și apoi va ieși. Când și metoda main() și metoda run() se vor fi terminat, se poate reda controlul sistemului. O altă modalitate de a crea thread-uri este aceea ca o clasă să implementeze interfața

Mai există și alți constructori în clasa Thread, cum ar fi: Thread (ThreadGroup ,Runnable, String). Parametrul ThreadGroup asignează thread-ul la un grup de thread-uri – mulțime de thread-uri ce permite tratarea unitară a tuturor thread-urile componente.

Parametrul de tip String suportă un nume pentru acest nou thread. Acest nume poate fi folosit împreună cu metoda getName() a clasei Thread pentru o referire de tip mnemonic a unui thread. Acești parametri sunt opționali (de altfel există 7 tipuri diferite de constructori pentru clasa Thread).

Thread-uri daemon

Multe sisteme prezintă thread-uri cu scopul de a facilita diverse servicii (servicii de I/O, ascultare pe socket, etc). Aceste thread-uri se află majoritatea timpului în starea idle și numai când primesc un mesaj încep să-și execute sarcina specifică. Aceste thread-uri sunt cunoscute sub numele de "Daemon Threads". Orice thread poate deveni daemon prin apelarea metodei proprii setDaemon() cu valoarea true. Se poate verifica starea unui thread prin intermediul metodei isDaemon().

Stările thread-urilor

Creând o instanță a unui thread acesta nu este lansat. Sarcina de a lansa thread-ul în execuție este realizată de metoda start().

Un thread se poate găsi în diferite stări în funcție de evenimentele petrecute.

Thread nou creat – Metoda run() nu este în execuție, timpul procesor nu este încă alocat. Pentru a porni un thread trebuie apelată funcția start(). În această stare se poate apela de asemenea metoda stop(), care va distruge thread-ul.

Thread în execuție – Thread-ul a fost lansat în execuție cu metoda start(). Este thread-ul pe care procesorul îl execută în acest moment.

Thread gata de execuție (runnable) – Thread-ul a fost startat dar nu se află în execuție în acest moment.Motivul ar fi acela că thread-ul a renunțat la procesor apelând metoda yield(), sau din cauza unui mecanism de programare a timpului procesor care a decis să distribuie acest timp altui thread. Thread-ul va putea trece în execuție când mecanismul de programare va decide acest lucru. Atâta timp cât există un alt thread cu o prioritate mai mare, thread-ul nu va trece în execuție.

Thread nepregătit pentru execuție (blocked) – Thread-ul nu poate fi executat din anumite motive. Ar putea să aștepte terminarea unei operații de tip I/O sau s-a apelat una din metodele wait(), sleep() sau suspend().

Prioritățile thread-urilor

Fiecărui thread îi este atribuită o prioritate cuprinsă între MIN_PRIORITY (egală cu 1) și MAX_PRIORITY (egală cu 10). Un thread moștenește prioritatea de la thread-ul care l-a creat, dar această prioritate se poate modifica apelând metoda setPriority(); valoarea acestei priorități se poate obține în urma apelului metodei getPriority().

Algoritmul de planificare întotdeauna va lansa thread-ul cu prioritatea cea mai mare în execuție. Dacă există mai multe thread-uri cu aceeași prioritate maximă atunci procesorul le va executa în maniera round-robin. Astfel un thread cu prioritate mai mică se poate executa numai atunci când toate thread-urile de prioritate mai mare sunt în starea non-runnable. Prioritatea thread-ului main() este NORM_PRIORITY (egală cu 5).

Grupuri de thread-uri

Fiecare thread aparține unui grup de thread-uri. Un grup de thread-uri este o mulțime de thread-uri (și posibil grupuri de thread-uri) împreună cu un mecanism de realizare a operațiilor asupra tuturor membrilor mulțimii. Grupul implicit de thread-uri este implicit numit main, și fiecare grup de thread-uri nou creat aparține acestui grup, mai puțin acelea specificate în constructorul său.

Pentru a afla pentru un thread la ce grup de thread-uri aparține se poate folosi metoda getThreadGroup(). Pentru a crea propriul grup de thread-uri, trebuie mai întâi să se creeze un obiect ThreadGroup. Se poate folosi unul din acești constructori:

ThreadGroup(String) – crează un nou ThreadGroup cu numele specificat.

ThreadGroup(threadGroup, String) – crează un nou ThreadGroup cu numele specificat și aparținând la un anumit grup de thread-uri.

După cum arată și al doilea constructor, un grup de thread-uri poate fi creat în interiorul altui grup de thread-uri. Cel mai nou grup de thread-uri creat devine membru la cel mai vechi realizându-se astfel o ierarhie de grupuri. Pentru a crea un thread în interiorul unui grup de thread-uri, altul decât grupul main trebuie doar menționat numele grupului atunci când se apelează constructorul thread-ului.

În momentul în care sunt mai multe thread-uri organizate într-un grup de thread-uri se poate apela la operații comune pentru toți membrii acestui grup.

Aceste operații sunt în principal stop(), suspend() and resume() care au aceeași semnificație ca atunci când se folosește un singur thread. Pe lângă aceste operații mai există și alte operații specifice grupului de thread-uri.

1.2.3. Desenarea în Java

În afara posibilității de a utiliza componente grafice standard, Java oferă și posibilitatea de control la nivel de punct (pixel) pe dispozitivul grafic, respectiv desenarea a diferite forme grafice direct pe suprafața unei componente.

Deși este posibil, în general nu se desenează la nivel de pixel direct pe suprafața ferestrelor. În Java a fost definit un tip special de componentă numită Canvas (pânză de pictor), al cărui scop este de a fi extins pentru a implementa componente cu o anumită înfățisare. Așadar clasa Canvas este o clasă generică din care se derivează subclase pentru crearea suprafețelor de desenare.

Constructorul Canvas() crează o planșă, adică o componentă pe care se poate desena. Planșele nu pot conține alte componente grafice, ele fiind utilizate doar ca suprafețe de desenat sau ca fundal pentru animație.

Constructor Canvas ()

Metode:

addNotify () crează planșa

paint(Graphics) pictează planșa în culoarea de background setată

Metoda paint() a clasei Canvas() pictează planșa în culoarea implicită a fundalului. Pentru a redesena planșa cu un alt conținut, se recomandă supradefinirea acestei metode implicite.

Toate desenele care trebuie să apară pe o suprafață de desenare se realizează în metoda public void paint(Graphics g), în general apelată intern în urma unui apel repaint(), ori de câte ori componenta respectivă trebuie reafișată. În general desenarea se poate face :

pe o porțiune de ecran,

la imprimantă sau

într-o zonă virtuală de memorie

Înainte ca utilizatorul să poată desena el trebuie să obțină un context de desenare pentru fereastra căreia îi aparține regiunea pe care se va desena. Acest context grafic este specificat prin intermediul obiectelor de tip Graphics primite ca parametru în funcția paint(). În funcție de dispozitivul fizic pe care se face afișarea (ecran, imprimantă, plotter, etc) metodele de desenare au implementări interne diferite, transparente utilizatorului. Așadar, clasa Graphics oferă posibilitatea de a desena linii, forme geometrice, imagini și caractere.

Constructor Graphics () construiește un nou obiect grafic

Metode:

– clearRect (int, int, int, int) ->șterge dreptunghiul indicat prin umplerea cu culoarea de fundal curentă a suprafeței curente de desen

– clipRect(int, int, int, int) -> taie un dreptunghi

– copyArea(int, int, int, int, int, int) ->copiază o arie de pe ecran

– create() -> crează un nou obiect grafic , copie a obiectului frafic inițial

– create(int, int, int, int) -> crează un nou obiect grafic cu parametrii indicate având la bază obiectul grafic inițal

– dispose() -> aranjează contextual grafic

– draw3DRect(int, int, int, int, boolean)-> desenează un dreptunghi

– drawArc(int, int, int, int, int, int) -> desenează un arc legat de dreptunghiul specificat de la startAngle la endAngle

– drawBytes(bytest, int, int, int, int) -> desenează biții specificați folosind fontul și culoarea curente

– drawChars(charst, int, int, int, int)-> desenează caracterele specificate folosind fontul și culoarea curente

– drawImage(Image, int, int, ImageObserver) -> desenează imaginea specificată la coordonatele (x,y) specificate

– drawImage(Image, int, int, int, int, ImageObserver) -> desenează imaginea specificată în interiorul dreptunghiului specificat

– drawImage(Image, int, int, Color, ImageObserver)-> desenează imaginea specificată la coordonatele (x,y) specificate cu fundalul color dat

– drawImage (Image, int, int, int, int, Color, ImageObserver)-> desenează imaginea specificată în interiorul dreptunghiului specificat cu fundalul color dat

– drawLine(int, int, int, int)-> desenează o linie între coordonatele (x1,y1) și (x2,y2)

– drawOval(int, int, int, int) ->desenează un oval în dreptunghiul specificat folosind culoarea curentă

– drawPolygon(intst, intst, int)-> desenează un pologon definit de o mulțme de puncte x și y

– drawPolygon(Polygon)-> desenează un pologon definit de un punct specificat

– drawRect(int, int, int, int)-> desenează conturul dreptunghiului specificat folosind culoarea curentă

– drawRoundRect(int, int, int, int, int, int) -> desenează conturul unui dreptunghi cu marginile rotunjite folosind culoarea curentă

– drawString(String, int, int)-> desenează un șir specificat folosind fontul și culoarea specificate

– fill3DRect(int, int, int, int, boolean)-> desenează un dreptunghi 3D folosind culoarea curentă

– fillArc(int, int, int, int, int, int) -> umple un arc folosind culoarea curentă

– fillOval(int, int, int, int)-> umple un oval în dreptunghiul specificat folosind culoarea curentă

– fillPolygon(intst, intst, int) -> umple un poligon în culoarea curentă folosind regula de umplere even-odd

– fillPolygon(Polygon) -> umple poligonul specificat în culoarea curentă folosind regula de umplere even-odd

– fillRect(int, int, int, int)->umple dreptunghiul specificat în culoarea curentă

– fillRoundRect(int, int, int, int, int, int)-> desenează un dreptunghi rotunjit colorat în culoarea curentă

– finalize() -> dispune de contextul grafic la care nu se mai face referire

– getClipRect()-> returnează dreptungiul legat de dreptunghiul de decupare

– getColor() -> aduce culoarea curentă

– getFont() -> aduce fontul curent

– getFontMetrics() -> aduce valoarea fontului curent

– getFontMetrics(Font) -> aduce valoarea fontului curent pentru fontul specificat

– setColor(Color) -> setează culoarea curentă la culoarea specificată

-setFont(Font) -> setează fontul pentru toate toate operațiile de desen ulterioare

– setPaintMode() -> setează modul de desen de a suprascrie destinația în culoarea curentă

– setXORMode(Color) -> setează modul de desen de a alterna între culoarea curentă și noua culoare specificată

– toString()-> returnează un obiect String reprezentând valoarea obiectului de tip Graphics

– translate(int, int)-> transformă parametrii specificați în contextual grafic original

Prin dreptunghi de decupare (clip area) se înțelege zona din suprafața componentei de afișare în care sunt vizibile operațiile efectuate. Orice operație efectuată în afara acestui dreptunghi nu are nici un efect. Stabilirea unui dreptunghi de decupare se realizează prin :

clipRect(int x, int y, int width, int height)

Proprietățile contextului grafic

culoarea de desenare

Color getColor()

void setColor(Color)

originea coordonatelor – poate fi modificată prin :

translate(int x, int y)

modul de desenare

void setXorMode() – scriere “sau exclusiv”

(culoare + fundal = culoare,

culoare + culoare = fundal,

(culoare + culoare1) + culoare = culoare1 )

void setPaintMode() – suprascriere

fontul curent pentru desenarea caracterelor

Font getFont()

void setFont(Font)

zona de decupare (în care sunt vizibile modificările)

Shape getClip()

void setClip(Shape)

void setClip(int x, int y, int w, int h)

În Swing, pentru a eficientiza desenarea, obiectul de tip Graphics primit

ca argument de metoda paintComponent este refolosit pentru desenarea componentei, a chenarelor și a fiilor săi. Din acest motiv este foarte important ca atunci cand se supradefinește metoda paintComponent sa se asigure că la terminarea metodei starea obiectului Graphics este aceeași ca la început.

Acest lucru poate fi realizat fie explicit, fie folosind o copie a contextului grafic primit ca argument:

// 1.Explicit

// 2. Folosirea unei copii

1.2.4. Pachetele AWT și SWING

O interfață grafică se crează de obicei cu sprijinul sistemului de operare (printr-o componentă numită server grafic).

Limbajul Java pune la dispoziția programatorului două biblioteci pentru realizarea unei interfețe grafice: java.awt și javax.swing. În figură sunt expuse clasele corespondente cu cele din awt:

   Fig. 1.1 Clase awt

În plus față de pachetul standard awt, pachetul swing adaugă noi clase care permit îmbunătățirea interfeței realizate. În figura următoare sunt prezentate clasele noi introduse de către swing:

   Fig.1.2 Clase noi awt

Tehnologia Swing face parte dintr-un proiect mai amplu numit JFC (Java Foundation Classes) care pune la dispoziție o serie întreagă de facilități pentru scrierea de aplicații cu o interfață grafică mult îmbogățită funcțional și estetic față de vechiul model AWT.

În JFC sunt incluse următoarele:

Componente Swing

Sunt componente ce înlocuiesc și în același timp extind vechiul set oferit de modelul AWT.

Look-and-Feel

Permite schimbarea îınfățișării și a modului de interacțiune cu aplicația în funcție de preferințele fiecăruia. Același program poate utiliza diverse moduri Look-and-Feel, cum ar fi cele standard Windows, Mac,Java, Motif sau altele oferite de driver și dezvoltatori, acestea putând fi interschimbate de către utilizator chiar la momentul execuției .

Accessibility API

Permite dezvoltarea de aplicații care să comunice cu dispozitive utilizate de catre persoane cu diverse tipuri de handicap, cum ar fi cititoarede ecran, dispozitive de recunoaștere a vocii, ecrane Braille, etc.

Java 2D API

Folosind Java 2D pot fi create aplicații care utilizează grafica la un nivel avansat. Clasele puse la dispoziție permit crearea de desene complexe,efectuarea de operații geometrice (rotiri, scalări, translații, etc.),prelucrarea de imagini, tipărire, etc.

Drag-and-Drop

Oferă posibilitatea de a efectua operații drag-and-drop între aplicații Java și aplicații native.

Internaționalizare

Internaționalizarea și localizarea aplicațiilor sunt două facilități extrem de importante care permit dezvoltarea de aplicații care să poată fi configurate pentru exploatarea lor în diverse zone ale globului, utilizând limba și particularitățile legate de formatarea datei, numerelor sau a monedei din zona respectivă.

1.2.4.1 Ferestre și butoane

Oricărei aplicații grafice îi corespunde o fereastră principală (de tip FRAME) și una sau mai multe ferestre adiționale.În swing există trei clase pentru gestionarea ferestrelor: Jframe, JWindow si JDialog.

Clasa JFrame permite crearea unei ferestre de aplicație. Fereastra are o bară de titlu, o margine, butoane de minimizare, maximizare și închidere (butoane "system").

Clasa JWindow permite crearea unei ferestre fără bara de titlu, meniu, butoane sistem etc.

Clasa JDialog permite crearea de ferestre de dialog. Ferestrele de dialog sunt dependente de ferestrele părinte de tip Frame. O fereastră de dialog poate fi modală (blochează aplicația până la închiderea dialogului) sau nemodală (nu blochează).

Pentru a crea ferestre de afișare a unor mesaje se poate utiliza direct o funcție statică, fără a mai crea explicit un obiect tip dialog:

JOptionPane.showMessageDialog(frame, “Mesajul meu.");

Pentru ferestre de dialog standard există clase specializate: JFileChooser și JColorChooser. Acestea pot fi utilizate pentru a selecta un fișier sau a alege o culoare.

Crearea unei ferestre principale:

public static void main(String args[]) {
   JFrame win = new JFrame(“Titlul ferestrei");
   win.setSize(200, 200);
   win.show();
}

Pentru a accesa conținutul unei ferestre se va folosi funcția getContentPanel():

Container c = win.getContentPane();

Pentru a obține închiderea automată a aplicației atunci când se apasă butonul de Close, se va utiliza metoda:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Pentru a organiza elementele intr-o fereastra se vor utiliza panouri. Swing pune la dispozitie doua tipuri de panouri: JPanel (panou simplu) si JScrollPane (panou cu derulare).

Butoanele derivă din clasa JButton. În costructor primesc textul afișat pe buton. Prin procedura setMnemonic se pot asocia taste de apelare rapidă (shortcut).

Pentru a adăuga un cuvânt de comandă asociat butonului (cuvânt ce va fi testat pentru efectuarea acțiunii asociate) se folosește metoda addActionCommand().

JButton buton = new JButton("I'm a Swing button!");
buton.setMnemonic('i');
buton.addActionCommand("butonulSwing");

JPanel panouButon = new JPanel();
panouButon.add(buton);

CAPITOLUL 2: PREGĂTIREA MEDIULUI DE LUCRU

2.1 Instalare JRE și NetBeans

JRE – Java Runtime Engine este un interpretor, o mașină virtuală pentru programe scrise în Java. JRE este proprietatea Oracle și utilizarea lui este gratuită.

JRE asigură portabilitatea programelor scrise în Java pe diverse sisteme de operare, de exemplu același program de validare MFP poate fi rulat atât pe sisteme Windows, cât și pe Linux.
Trebuie doar să se aleagă și să se instaleze un JRE adecvat pentru sistemul de operare.

Pașii necesari pentru instalarea versiunii actuale sunt:
1. Download versiunea cea mai nouă
2. Instalarea versiunii noi
3. Verificarea instalării

Pentru a rula, clic Run.

Pentru a salva fișierul pentru o instalare ulterioară, clic Save.
Selectează folderul și salvează fișierul în sistem
Tip: Salvează fișierul într-o locație cunoscută, spre exemplu pe desktop
Dublu-clic pe fișierul salvat pentru a începe instalarea

Procesul de instalare începe.Clic pe butonul Install pentru a accepta termenii de instalare și a continua instalarea

Fig 2.5 Splashscreen welcome java

O scurtă casetă de dialog confirmă ultimii pași ai procesului de instalare

click Close

Aceasta va completa procesul de instalare Java.

Fig 2.6 Confirmare instalare java

NetBeans este un proiect open-source, cu o bază de utilizatori foarte mare, o comunitate în creștere și peste 100 de parteneri (în creștere!) din toată lumea. Sun Microsystems a fondat proiectul open source NetBeans în iunie 2000 și continuă să fie principalul sponsor al proiectului.

Astăzi există două produse: NetBeans IDE și platforma NetBeans.

NetBeans IDE este un mediu de dezvoltare – un instrument pentru programatori, pentru scrierea, compilarea, testarea, depanarea, proiectarea și instalarea programelor. Este scris în Java – dar poate accepta orice limbaj de programare. De asemenea, există un număr imens de module pentru extinderea NetBeans IDE. NetBeans IDE este un produs gratuit, fără restricții legate de modul de utilizare.

De asemenea, este disponibilă Platforma NetBeans; o bază modulară și extensibilă, utilizată drept conector software pentru crearea aplicațiilor desktop puternice. Partenerii ISV oferă Plugin-uri cu valoare adăugată, care se integrează ușor în platformă și care pot fi utilizate, de asemenea, la dezvoltarea propriilor instrumente și soluții.

Ambele produse sunt open-source și gratuite pentru uz comercial și necomercial. Codul sursă este disponibil pentru reutilizare, conform Common Development and Distribution License (CDDL – Licența de distribuție și dezvoltare comună).

Aplicația a fost realizată în mediul de dezvoltare NetBeans IDE 8.0.2. Aceasta se downloadează gratuit de pe www.netbeans.org.

NeatBeans IDE se instalează pe computer în funcție de preferințele utilizatorului (unde să fie instalat, update-uri). Dupa ce a fost instalat la rularea în execuție a mediului Netbeans IDE va apărea un splashscreen :

Fig. 2.3 Splashcreen NetBeans

După încărcarea modulelor necesare rulării va începe execuția propriu-zisă a mediului de dezvoltare :

Fig 2.4 Mediul de lucru NetBeans

Pentru a putea lucra în acest mediu trebuie să fie instalat împreună cu JDK, această platformă fiind necesară pentru a putea realiza aplicații Java. JDK poate fi descărcată gratuit de pe http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

Kitul Java (JDK) este o implementare a uneia dintre urmatoarele platforme Java SE, Java EE sau Java ME lansate de corporația Oracle sub forma unui produs binar folosit de dezvoltatorii Java la Solaris, Linux, Mac OS X sau Windows. JDK include un JVM individual și alte resurse necesare dezvoltării unei aplicații Java. O dată cu introducerea platformei Java, a fost de departe cel mai utilizat soft de dezvoltare folosit pe scară largă. Pe 17 Noiembrie 2006, Sun a anunțat că va fi relansat sub formă de licență gratuită. Acest lucru a fost în general posibil din 8 Mai 2007 când Sun a contribuit la realizarea acestei noi versiuni gratuite Java.

Instalarea aplicației

Instalarea JDK pentru Microsoft Windows

Instalarea presupune rularea fișierului de instalare prin dezarhivare și instalarea JDK. Parte a JDK, instalarea are o opțiune de includere a versiunii publice a Java Runtime Environment ( JDK include de asemenea o versiune JRE individuală folosită doar de tool-uri). Pentru instalare se urmează pașii:

Download a aplicației

În cazul salvării fișierului cu instalare automată fără rularea acestuia de pe pagina de descărcare a site-ului web, acesta va avea mărimea de biți menționată pe pagina de descărcare. Dupa descărcarea completă, se verifică dacă s-a descărcat un software complet și fără erori.

Se rulează JDK Installer

Se instalează JDK Silently

Este nevoie de drepturi de administrare pentru instalarea JDK la Microsoft Windows.

Fișierul jdk-7<version>-windows-i586-i.exe permite instalarea JDK la un sistem de 32 biți. În acest caz prima condiție este minim un procesor Pentium 2 266 MHz. A doua condiție se referă la spațiul de pe disc.

Pentru JDK există posibilitatea instalării:

Development Tools

Source Code

Public Java Runtime Environment

Pentru JDK, imaginea instalată constă în toate fișierele instalate sub directorul jdk1.8.0; directorul Program Files\Common Files\Java\Java Update, sau Program Files (x86)\Common Files\Java\Java Update pentru sistemele cu 64 biți conțin Java Update, ceea ce permite un update automat al computerului cu ultimele versiuni.

Imaginea va fi automat instalată în Windows drive – drive-ul unde sistemul de operare Windows este instalat ( system drive ) . Cel mai adesea acesta va fi partiția C. Cu toate acestea, este posibil ca instalarea să fie efectuată pe orice drive. Spre exemplu, acesta poate fi instalat pe un drive non-Windows cu o instalare normală. În completare la cerințele de spațiu pentru instalare, trebuie să existe sufficient spațiu pe disc pentru Java Update.

În următorul tabel sunt prezentate cerințele minime ale JDF privind spațiul pe disc:

A treia condiție se referă la cerințele minime ale sistemul de operare cu 32 biți privind memoria, conform tabelului de mai jos:

Fisierul jdk-7<version>-windows-x64.exe permite instalarea JDK la un sistem de 64 biți.În cazul în care a fost descărcat fișierul și nu a fost rulat direct de pe web site, se face dublu clic pe icoana de instalare. Apoi se urmează instrucțiunile oferite și este posibil să se solicite reboot pentru computer. Dupa terminarea instalării, fișierul descărcat se poate șterge în vederea recuperării spațiului pe disc.

În acest caz prima condiție este minim un procesor Pentium 2 266 MHz. A doua condiție care se referă la spațiul pe disc sunt aceleași ca la sistemul de operare Windows de 32 biți. Spațiul necesar tool-urilor este de 181 MB. A treia condiție privind memoria se referă la cel puțin 128 MB de memorie.

Se updatează PATH Variable (Optional)

JDK se poate rula fără setarea PATH environment variable, sau opțional se poate seta pentru a rula fișierele executabile JDK (javac.exe, java.exe, javadoc.exe, and so forth) din orice director fără a scrie toată comanda. Dacă nu se setează variabila PATH, este nevoie să se specifice comanda completă în fișierul executabil de fiecare dată când se rulează:

C:\> "C:\Program Files\Java\jdk1.7.0\bin\javac" MyClass.java

Este util să se seteze variabila PATH permanent astfel încât să rămână salvată dupa reboot.

Pentru a seta variabila PATH permanent, se adaugă comanda integrală a jdk1.7.0\bin directory la variabila PATH . Comanda completă are forma C:\Program Files\Java\jdk1.7.0\bin. Setarea variabilei PATH pentru Microsoft Windows:

Clic Start -> Control Panel -> System.

Clic Advanced ->Environment Variables.

Adaugă locația folderului bin din cadrul JDK pentru instalarea variabilei PATH în System Variables. Următoarea este o valoare tipică pentru variabila PATH :

C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Java\jdk1.7.0\bin

Se utilizează JDK

Dezinstalarea JDK

Pentru dezinstalarea JDK, se folosește funcția "Add/Remove Programs" din Microsoft Windows Control Panel.

2.2 CREAREA UNEI APLICAȚII

Se selectează File | New Project și se alege modulul NetBeans. Se selectează "NetBeans Platform Application" conform imaginii de mai jos:

Fig 2.7 Creare proiect nou NetBeans

Click Next

Se salvează noua aplicație cu denumirea "WordProcessor" și se specifică un folder pentru salvarea acesteia

Fig 2.8 Configurarea numelui și a locației

Click Finish. Noul proiect va apărea în fereastra Projects

Crearea Modulului

În această secțiune, în primul rând se crează modulul Platformei NetBeans

Click dreapta pe "Modules"conform screenshot-ului de mai jos și selectare "Add New"

Noul modul se denumește "WordEditorCore":

Fig 2.8 Finalizare configurare nume și locație

Click Next:

Se specifică "org.word.editor.core" ca și element unic de identificare a modulului, care este baza codului sau împreună cu un nume de display care va fi arătat în fereasta Project

Fig 2.9 Configurare modul

Click Finish. Noul modul este creat și structura sa este prezentată în fereasta Projects :

Crearea ferestrei

În această secțiune se crează prima fereastră NetBeans

Se face click dreapta pe modulul "WordEditorCore" și se selectează New | Other. În cadrul modulului Development se selectează "Window":

Fig 2.10 Crearea ferestrei

Click Next

În acest punct ar trebui să apară o fereastră unde se va specifica poziția noii ferestre în cadrul aplicației, precum și dacă se va deschide automat o dată cu lansarea aplicației, împreuna cu alte setări:

Fig 2.11 Setari de baza

La următorul pas, se selectează "editor", care este poziția centrală predefinită din cadrul aplicației și "Open on Application Start".

Click Next

Se setează "Word" în câmpul << class name >> și "org.word.editor.core" în campul << package>>

Fig 2.12 Setare nume,pictograma si locatie

Click Finish. Noua fereastră va fi adăugată la structura sursa a modulului:

Dublu click pe fișierul "WordTopComponent.java"pentru deschiderea acestuia din meniul Design din cadrul "Matisse" GUI Builder

Fig 2.13 Design

Se folosește Palette (Ctrl-Shift-8) pentru a adăuga un câmp sau un text în cadrul ferestrei:

Fig 2.14 Adaugare text

Urmează pașii pentru a face noile component GUI utilizabile

Click dreapta în zona textului, se selectează "Change Variable Name"și se denumește "text".

Click dreapta pe buton, se alege "Edit Text" și se modifică opțiunea text în "Filter!"

Dublu click pe buton pentru a crea un eveniment în mod automat în Source editor. Această modalitate se poate folosi prin simplu click pe buton.Se schimbă conținutul metodei cu următorul cod

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {.

String s = text.getText();. s = s.toUpperCase();

text.setText(s);

}

Rularea aplicaȚiei

În această secțiune se lansează aplicația

Click dreapta pe aplicația WordProcessor și se selectează Run. În acest fel se va lansa noua aplicație a platformei NetBeans și se instalează modulul. Va apărea o fereastră nouă și un nou meniu pentru deschidere precum în figura de mai jos

Fig 2.15 Lansarea aplicației

Se inserează un text scris cu litere mici în zona de text și click pe "Filter!"Acum textul ar trebui să apară scris cu majuscule

M

Fig 2.16 Rularea aplicației

În acest stadiu orice este capabil să creeze o nouă aplicație NetBeans și să adauge noi module.

CAPITOLUL 3: DESCRIEREA APLICAȚIEI

3.1 Structura aplicației

Programul a fost creat ca o aplicație Java SE (inițialele SE provin de la Standard Edition) , care este o colecție de biblioteci java, necesare creării unei aplicații de tip desktop. Interfața utilizator grafică (engl.: GUI – Graphical User Interface) permite utilizatorului să comunice cu aplicația, folosind în acest scop obiecte grafice de pe ecran: ferestre, butoane, casete de validare, meniuri, etc. Acționarea asupra acestora se face folosind tastatura sau dispozitive de intrare speciale, dintre care cel mai răspandit este mouse-ul.

În Java există diferite pachete de clase care permit realizarea de interfețe grafice precum java.awt și java.swing. Inițialele AWT provin de la Abstract Window Toolkit – set de dezvoltare de ferestre abstracte. Acest set permite realizarea de interfețe grafice care nu depind de platforma pe care rulează aplicația. El oferă programatorului clase de componente organizate sub forma unei ierarhii care are ca rădacina clasa Component. Celălalt pachet, SWING, este construit peste AWT și conține un număr mai variat de componente.

Folosirea interfețelor grafice implică și o abordare specială în programare, numită programare orientată pe evenimente (engl: Event Oriented Programming) sau programare ghidată de evenimente (engl.: Event Driven Programming). În această concepție, obiectele din program pot fi surse de evenimente sau consumatoare ("ascultătoare") de evenimente (eng.: Event Listeners). Evenimentele însuși sunt obiecte (instanțe ale unor clase de evenimente ) generate de surse și interceptate de consumatori. Clasele consumatoare de evenimente sunt cele care conțin metodele prin care aplicația reacționează la evenimentele respective.

Se disting evenimente de nivel inferior (cele generate de diferite componente) și evenimente abstracte (care reprezintă diferite evenimente conceptuale, independente de componenta care le-a generat). Fiecărei clase de evenimente îi corespunde o interfață pe care trebuie să o implementeze clasele concepute de programator, care interceptează și tratează evenimentele respective. Interfețele sunt, de asemenea organizate într-o ierarhie, similară celei a claselor. Pentru unele interfețe s-au realizat și clase-prototip care le implementează, numite adaptoare. Clasele de evenimente, interfețele și adaptoarele se găsesc în pachetul java.awt.event.

Ca structură, aplicația conține trei pachete: " matematica ", "razvan.master.matematica" și "razvan.master.matematica.GUI".

Pachetul implicit al aplicației este "matematica", și conține doar clasa principală de care aparține metoda main. Această metodă este prima rulată la pornirea aplicației și se ocupă cu inițializarea și afișarea ferestrei principale:

public static void main(String[] args) {

JFrameMain jframeMain = new JFrameMain();

jframeMain.setVisible(true);

}

Al doilea pachet al aplicației, "razvan.master.matematica", conține clasele care implementează algoritmii matematici. Acestea folosesc tehnici de programare orientată obiect (OOP – Object Oriented Programming) precum moștenire și polimorfism.

Structura claselor este prezentată în schema următoare:

Clasa MathBase introduce toate metodele care ulterior vor fi implementate de algoritmi:

public class MathBase {

// Returneaza descrierea algoritmului

public String getDescription()

// Returneaza tipul de algoritm

public static int getAlgorithmType()

// Returneza numele algoritmului

public static String getAlgorithmName()

// Se executa pentru a calcula rezultatul

public boolean Run()

// Returneaza ultima eroare aparuta

public final String getLastErrorMsg()

// sterge toti parametrii

public void clearParams()

// Adauga un parametru

public void addParam(long value)

// Returneaza valoare parametrului cu indexul specificat

public long getParamValue(int index)

// Numarul parametrilor necesari pentru rezolvarea algoritmului

public int getRequiredParamCount()

// returneaza rezultatul cu nr. "resultIndex"

public String getResultAsString(int resultIndex)

// returneaza numarul de rezultate

public int getResultCount()

}

Clasele MathSingleLongResultAlgorithm și MathMultiDoubleResultAlgorithm derivează din clasa de bază MathBase și sunt specializate pe returnarea unui singur rezultat întreg și respectiv a unui număr nelimitat de rezultate de tip real.

Clasa MathFactorial derivează din MathSingleLongResultAlgorithm și este specializată în calcularea factorialului unui număr natural:

public class MathFactorial extends MathSingleLongResultAlgorithm {

protected long doFactorial(long value)

}

Clasele MathArrangement, MathPermutation și MathCombination sunt derivate din MathFactorial și implementează algoritmii de calcul al aranjamentelor, permutărilor și combinărilor.

Clasa MathWithCanvas derivează din MathMultiDoubleResultAlgorithm și adaugă o nouă funcționalitate numită Canvas. Componenta Canvas se găsește în pachetul AWT (java.awt.Canvas), și reprezintă o suprafață dreptunghiulară a ecranului unde o aplicație poate desena folosind componente specializate precum java.awt.Graphics și java.awt.Graphics2D:

public class MathWithCanvas extends MathMultiDoubleResultAlgorithm {

// Introduce functionalitatea Canvas

protected class MathCanvas extends Canvas {

}

// Se foloseste pentru a desena

protected void doPaint(Graphics g)

}

Clasa MathQuadraticEquation derivează din MathWithCanvas și implementează algoritmul de rezolvare și desenare a graficului ecuațiilor de gradul I si II.

Clasa MathUtils definește câteva constante folosite de celelalte clase:

public class MathUtils {

public static final int ALGORITHM_UNDEFINED = -1;

public static final int ALGORITHM_ARRANGEMENTS = 0x00000001;

public static final int ALGORITHM_PERMUTATIONS = 0x00000002;

public static final int ALGORITHM_COMBINATIONS = 0x00000004;

public static final int ALGORITHM_QUADRATIC_EQUATION = 0x00000008;

public static final String ALGORITHM_UNDEFINED_NAME = "";

public static final String ALGORITHM_ARRANGEMENTS_NAME = "Aranjamente";

public static final String ALGORITHM_PERMUTATIONS_NAME = "Permutari";

public static final String ALGORITHM_COMBINATIONS_NAME = "Combinari";

public static final String ALGORITHM_QUADRATIC_EQUATION_NAME = "Ecuatia de gradul 2";

}

Clasa MathAlgorithmFactory implementează două metode cu ajutorul cărora se instanțiază algoritmii implementați, pornind de la tipul sau numele algoritmului:

public class MathAlgorithmFactory {

public static MathBase createAlgorithm(String algorithmName) {

switch (algorithmName) {

case MathUtils.ALGORITHM_ARRANGEMENTS_NAME:

return new MathArrangement();

case MathUtils.ALGORITHM_COMBINATIONS_NAME:

return new MathCombination();

case MathUtils.ALGORITHM_PERMUTATIONS_NAME:

return new MathPermutation();

}

return null;

}

public static MathBase createAlgorithm(int algorithmType) {

switch (algorithmType) {

case MathUtils.ALGORITHM_ARRANGEMENTS:

return new MathArrangement();

case MathUtils.ALGORITHM_COMBINATIONS:

return new MathCombination();

case MathUtils.ALGORITHM_PERMUTATIONS:

return new MathPermutation();

}

return null;

}

}

Al treilea pachet al aplicației, "razvan.master.matematica.GUI", conține toate ferestrele aplicației care, împreună cu componentele de pe ele, reprezintă interfața grafică utilizator:

JFrameMain – fereastra principală a aplicației;

JDialogCombinatorics – fereastra de evaluare a algoritmilor combinatorici;

JDialogQuadraticEquation – fereastra de evaluare a ecuațiilor;

JDialogEquationGraph – fereastra în care se desenează graficele funcțiilor;

JDialogAbout – conține informații despre aplicație.

3.2 Aplicații matematice în Java

3.2.1 Combinatorica

Aplicația implementează algoritmii combinatorici prin derivarea metodei Run din clasa de baza MathBase. În programarea orientată obiect, tehnica se numește polimorfism. Această tehnică se traduce prin faptul că o metodă declarată în clasa de bază produce rezultate diferite în funcție de implementarea specifică a fiecărei clase care derivează din clasa de baza.

În clasa de bază se verifică doar dacă numărul de parametri introduși este cel corect:

public class MathBase {

public boolean Run() {

if (parameterList.size() == this.getRequiredParamCount())

return true;

else {

this.lastErrorMessage = "Lipsesc datale de intrare.";

return false;

}

} }

Clasa MathFactorial este specializată în calculul factorialului care se realizează prin implementarea aceleiași metode Run:

public class MathFactorial extends MathSingleLongResultAlgorithm {

public boolean Run() {

if (!super.Run())

return false;

long factorial = this.getParamValue(0);

if (factorial < 0) {

this.lastErrorMessage = "Factorialul se calculeaza pentru valori pozitive.";

return false; }

try {

this.result = doFactorial(factorial);

if (this.result > 0) {

return true; }

else {

this.lastErrorMessage = "Eroare de calcul. Valoare prea mare a factorialului.";

return false; }

} catch (Exception e) {

this.result = 0;

this.lastErrorMessage = e.getMessage();

return false;

} } }

Algoritmii combinatorici sunt derivați din clasa factorial și reimplementează la rândul lor metoda Run pentru a calcula rezultatul conform formulelor matematice:

public class MathArrangement extends MathFactorial {

public boolean Run() {

if (!super.Run())

return false;

long n = this.getParamValue(0);

long k = this.getParamValue(1);

if ((n < 0) || (k < 0)) {

this.lastErrorMessage = "Valori invalide pentru \"n\" sau \"k\".";

return false;

}

if (k > n) {

this.lastErrorMessage = "Valoarea lui \"k\" nu poate fi mai mare decat valoarea lui \"n\".";

return false;

}

try {

this.result = doFactorial(n) / doFactorial(n – k);

if (this.result > 0) {

return true;

}

else {

this.lastErrorMessage = "Eroare de calcul. Valori prea mari ale factorialului.";

return false;

}

} catch (Exception e) {

this.result = 0;

this.lastErrorMessage = e.getMessage();

return false;

} } }

public class MathCombination extends MathFactorial {

public boolean Run() {

if (!super.Run())

return false;

long n = this.getParamValue(0);

long k = this.getParamValue(1);

if ((n < 0) || (k < 0)) {

this.lastErrorMessage = "Valori invalide pentru \"n\" sau \"k\".";

return false;

}

if (k > n) {

this.lastErrorMessage = "Valoarea lui \"k\" nu poate fi mai mare decat valoarea lui \"n\".";

return false;

}

try {

this.result = doFactorial(n) / (doFactorial(k) * doFactorial(n – k));

if (this.result > 0) {

return true;

}

else {

this.lastErrorMessage = "Eroare de calcul. Valori prea mari ale factorialului.";

return false;

}

} catch (Exception e) {

this.result = 0;

this.lastErrorMessage = e.getMessage();

return false;

} } }

În interfața grafică, utilizatorul alege algoritmul dorit, introduce valorile pentru "n" si "k" și apasă pe butonul "Calculeaza" pentru a obține rezultatul.

Fig 3.16 Introducere valori

3.2.2 Ecuații

Ecuația de gradul II, cât și cazul particular al ecuației de gradul I, când se introduce valoarea 0 pentru coeficientul "a" al ecuației, sunt implementate de clasa MathQuadraticEquation. Ca și în cazul algoritmilor combinatorici, clasa implementează metoda Run pentru obținerea soluțiilor:

public class MathQuadraticEquation extends MathWithCanvas {

public boolean Run() {

this.canDrawGraphics = false;

if (!super.Run())

return false;

this.result.clear();

this.lastErrorMessage = "";

this.canDrawGraphics = false;

double a = this.getParamValue(0);

double b = this.getParamValue(1);

double c = this.getParamValue(2);

if (a == 0) {

if (b == 0) {

if (c == 0) {

this.lastErrorMessage = "Solutia este intreaga multime de definitie.";

} else {

this.lastErrorMessage = "Ecuatia nu are solutii.";

}

return false;

} else {

double x = (-1) * c / b;

this.result.add(x);

}

} else {

double delta = (b * b) – (4 * a * c);

if (delta < 0) {

this.lastErrorMessage = "Ecuatia nu are solutii.";

return false;

} else if (delta == 0) {

double x = ((-1) * b) / (2 * a);

this.result.add(x);

} else {

double x1 = (((-1) * b) – (Math.sqrt(delta))) / (2 * a);

double x2 = (((-1) * b) + (Math.sqrt(delta))) / (2 * a);

this.result.add(x1);

this.result.add(x2);

}

this.Vx = ((-1) * b) / (2 * a);

this.Vy = ((-1) * delta) / (4 * a); }

this.pA = a;

this.pB = b;

this.pC = c;

this.canDrawGraphics = true;

return true;

} }

În plus față de ceilalți algoritmi, clasa mai implementează și metoda folosită pentru desenarea graficului:

protected void doPaint(Graphics g) {

super.doPaint(g);

drawAxes(g);

if (this.canDrawGraphics) {

drawEquation(g);

} }

Interfața grafică utilizator conține descrierea ecuației, componente de tip javax.swing.JSpinner pentru introducerea valorilor parametrilor, o componentă de tip javax.swing.JTextArea pentru afișarea rezultatelor și un buton pentru rezolvarea ecuației.

Fig 3.17 Introducere date pentru ecuație

Prin apăsarea butonul "Calculeaza" se obțin rezultatele:

Fig 3.18 Rezultatul soluției

Pentru a vizualiza graficul ecuației, utilizatorul trebuie să apese pe butonul "Grafic":

Fig 3.19 Graficul funcției

BIBLIOGRAFIE

1. Athanasiu Irina, Costinescu B., Drăgoi O.A., Popovici F.I.  Limbajul Java. O perspectivă pragmatică. Editura Agora, Tg.Mureș

2. Fraizer C., Bond J.  Java API. Pachetele API java.applet si java awt. Editura Teora, București, 1998. .3. Rotariu E.  Limbajul Java.  Editura Agora, Tg.Mureș, 1996.

3. Norton P., Stanek W. Ghid de programare in Java.  Editura Teora, București, 1997

4. Prodan A., Prodan M.  Mediul Java pentru Internet. Editura Promedia Plus, Cluj-Napoca, 1997.

5. Rotariu E.  Limbajul Java.  Editura Agora, Tg.Mureș, 1996.

SURSE INTERNET

https://www.java.com/en/

http://www.oracle.com

https://netbeans.org/

http://ro.wikipedia.org/wiki/Java_%28limbaj_de_programare%29

http://www.cs.ucv.ro/staff/dtusaliu/dar/curs/limbajuljava/cap1.html

http://javacurs.weebly.com/

Similar Posts