Utilizarea Bibliotecii Swing Si a Jdbc Pentru Realizarea Interfetelor de Gestiune a Stocurilor
Cuprins
1 CAPITOLUL 1 : INTRODUCERE 1-5
1.1 Prefață 1-5
1.2 Scurt istoric[4] 1-5
1.3 Tehnologii de programare[4] 1-6
1.4 Limbajul C și C++[4] 1-6
1.5 Istoricul și caracteristicile limbajului Java[1] 1-7
1.6 Java vizavi de C/C++[2] 1-8
1.6.1 Tipuri de date 1-8
1.6.2 Pointeri 1-10
1.6.3 Gestionarea automata a memoriei 1-11
1.6.4 Clase 1-12
1.6.5 Lipsa preprocesorului 1-13
1.6.6 Alte diferente 1-14
2 CAPITOLUL 2 : GENERALITĂȚI 2-16
2.1 Mediul de dezvoltare a aplicațiilor Java[4] 2-16
2.2 Interfețe[1] 2-17
2.2.1 Declarațiile atributelor unei interfețe 2-18
2.2.2 Declarațiile metodelor unei interfețe 2-18
2.3 Crearea interfețelor grafice cu pachetul Swing 2-19
2.3.1 Utilizarea componentelor Swing 2-19
2.3.2 JLabel 2-20
2.3.3 JButton 2-22
2.3.4 JTextComponent 2-22
2.3.5 JPasswordField 2-23
2.3.6 JScrollBar 2-23
2.3.7 JSlider 2-23
2.3.8 JProgressBar 2-24
2.3.9 JComboBox 2-26
2.3.10 JList 2-27
2.3.11 Timer 2-27
2.4 Lucrul cu baze de date[3] 2-30
2.4.1 Introducere 2-30
2.4.1.1 Generalități despre baze de date 2-30
2.4.1.2 JDBC 2-31
2.4.2 Conectarea la o baza de date 2-31
2.4.2.1 Înregistrarea unui driver 2-32
2.4.2.2 Specificarea unei baze de date 2-32
2.4.2.3 Realizarea unei conexiuni 2-33
2.4.3 Efectuarea de secvențe SQL 2-33
2.4.3.1 Interfața Statement 2-33
2.4.3.2 Interfața ResultSet 2-34
3 CAPITOLUL 3 : PREGĂTIREA MEDIULUI DE LUCRU 3-36
3.1 NetBeans[4] 3-36
3.1.1 Descărcare și instalare NetBeans 3-36
3.1.2 Lucrul cu NetBeans 3-36
3.1.3 Cele mai utile 10 scurtături în NetBeans 3-41
3.2 Xampp 3-44
3.2.1 Despe Xampp[6] 3-44
3.2.2 Securitate în Xampp 3-45
4 Capitolul 4 : Descrierea aplicației 4-48
4.1 Logare 4-48
4.2 Intrări 4-49
4.3 Stoc 4-52
4.4 Ieșiri 4-53
4.5 Utilizator 4-53
4.5.1 Administrator 4-53
4.5.2 Utilizator 4-55
5 Concluzii 5-57
Bibliografie 5-58
CAPITOLUL 1 : INTRODUCERE
Prefață
Scopul acestei lucrări de diplomă constă în realizarea unei aplicații destinată oricărei intreprinderi ce lucrează cu stocurii. Aplicația dorește să fie ușor de utilizat și să țină cont de ce intră, ce iese și stocul din acel moment dintr-o ineprindere.
Lucrarea este structurată pe patru capitole:
Introducere
Generalități
Pregătirea mediului de lucru
Descrierea aplicației
În primul capitol se face o introducere în domeniul softwere cu o prezentare a limbajelor de programare C++ și Java, precum și o comparație între cele două.
În cel de-al doilea capitol se prezintă mai detaliat ceea ce se folosește la elaborarea lucrării. Aici ne sunt prezentate și explicate interfețele, creearea interfețelor, bazele de date, dar și lucrul, creearea, dezvoltarea și îmbinarea tuturor acestora.
Al treilea capitol ne prezintă două programe ce ne ajută și ne permite lucrul cu plicația.
În ultimul capitol este prezentată aplicația.
Scurt istoric[4]
Începand cu anul 1977 începe să se utilizeze pe scară largă calculatoarele personale, prețul acestora facându-le accesibile mari majorități. În 1981 IBM, cel mai mare producător de calculatoare, lansează pe piață modelul său de calculator personal – IBM PC (XT). Aproape peste noapte calculatoarele personale își fac apariția în intreprinderi, organizații și chiar în casele oamenilor. Initial aceste calculatoare personale erau folosite ca unități independente, transferul informațiilor de la un calculator la altul se facea prin intermediul dischetelor. Pentru a eficientiza schimbul informațiilor între calculatoarele personale acestea au fost interconectate fie prin legături telefonice fie în rețele locale în cadrul aceleiași clădiri (LANs – local area networks). Aceasta a dus la răspandirea aplicațiilor de calcul distribuit (distributed computing). În loc de a fi adunate și prelucrate centralizat, într-un centru de calcul dotat cu calculatoare foarte performante, datele se procesau distribuit, pe calculatoare personale conectate în rețea, amplasate în locurile în care informația era obținută. Puterea de calcul a unui calculator personal era suficientă pentru a asigura cerințele unui utilizator individual și comunicația în rețea.
La această oră un calculator personal de 1000$ are o putere de calcul impresionantă, fiind la fel de performant ca un calculator mare din anii 70, având prețul de un milion de dolari. Informația este distribuită prin rețea unde unele calculatoare numite File Servere au sarcina principală de a stoca programe și date iar altele numite Clienți apelează la serviciile serverelor pentru a accesa și procesa distribuit aceste date. Prelucrarea distribuită a datelor consta în “cooperarea” între aplicațiile executate pe calculatoarele client și cele executate de servere. Aplicația client solicită un anumit serviciu aplicației server, aceasta din urmă efectuează prelucrările necesare satisfacerii cererii clientului și îi transmite rezultatele solicitate. O aplicație dată de prelucrare distribuită constă nu dintr-un singur program executat pe un singur calculator ci din mai multe programe executate pe doua sau mai multe calculatoare interconectate în rețea. O astfel de aplicație se numește aplicație client/server.
În anii 70 și 80 limbajele de programare uzuale în elaborarea sistemelor de operare și a aplicațiilor client / server de prelucrare distribuită în rețea erau C și C++. Odată cu interconectarea rețelelor locale LAN în rețele WAN (wide area network) și dezvoltarea tehnologiilor Internet, limbajul de programare Java câstigă rapid teren oferind perspective noi pentru dezvoltarea aplicațiilor bazate pe aceste tehnologii.
Tehnologii de programare[4]
La începuturile sale programarea se făcea “dupa ureche” în funcție de talentul, experiența și de capacitatea de analiză și sinteză a programatorului. La proiectarea programului se pleca de la reprezentare grafică (schema logică) a algoritmului de rezolvare a problemei. O astfel de schemă logică este de fapt un graf orientat ale cărui noduri sunt operațiile de prelucrare a datelor reprezentate prin simboluri grafice adecvate. Nodurile sunt conectate prin arce orientate care stabilesc succesiunea de efectuare a operațiilor. O astfel de abordare a rezolvării oferă prea multă libertate în proiectarea algoritmului. Nu întamplator, în acea vreme cea mai importantă instrucțiune prezentată în manualele de programare era instrucțiunea de salt GOTO.
Limbajul FORTRAN avea foarte multe variante a acestei instrucțiuni. Datorită lipsei de restricții în proiectarea fluxului de calcul adeseori codul sursă devenea foarte “încurcat”, greu de înteles, de modificat și mai ales nesigur, în special în cazul programelor cu o complexitate ridicată. Activitatea de cercetare a dus la apariția, în anii 60, a conceptelor programării structurate care introducea o anumită disciplină în elaborarea programelor. Respectând principiile programării structurate, programele capată o structură precisă, sunt mai ușor de înțeles, de testat, de modificat și de depanat. În această abordare, la proiectarea programului nu mai este necesară elaborarea schemelor logice.
Deoarece în acea perioadă nu existau limbaje de programare care să ofere suport pentru programarea structurată, Nicklaus Wirth a elaborat în 1971 limbajul de programare Pascal (după numele matematicianului Blaise Pascal – creator al primei mașini mecanice de calcul) pentru a fi folosit la predarea programării în mediile academice. Cu acest limbaj, Wirth a introdus și conceptul de structură de date –indisolubil legat de algoritmul ce stă la baza programului. Pascal a devenit în scurt timp limbajul preferat predat în universități. Conceput în scopuri didactice limbajul avea o serie de slăbiciuni care au făcut să nu fie agreeat pentru dezvoltarea aplicatiilor comerciale, industriale și guvernamentale.
În anii 70-80 Departamentul Apărării al S.U.A. (DOD) a lansat o cerere pentru elaborarea unui limbaj de programare ce urma să înlocuiască sutele de limbaje de programare folosite la acea dată în sistemele sale. Noul limbaj urma să devină unicul limbaj de programare folosit în sistemele sale de calcul. Limbajul astfel obșinut s-a numit Ada (dupa numele primului programator al unei masini de calcul – construită de matematicianul Charls Babbage – Lady Ada Lovelace, fica poetului englez Lord Byron). Chiar dacă este un urmaș al Pascalului, limbajul Ada este mult diferit de acesta. El introduce printre altele mecanismul de multitasking care permite programatorului să definească procesări ale datelor care decurg în paralel.
C++ și Java prevăd și ele acest mecanism sub denumirea de multithreading. Am văzut că C++ și Java introduc în plus conceptul de programare orientată pe obiecte oferind și suportul necesar implementării acestuia. Conceptul de obiect “încapsulează” la un loc datele și procedurile de prelucrare a acestora într-o singură entitate, extinzând astfel conceptul de structură de date din Pascal.
Limbajul C și C++[4]
În anul 1970 la Bell Laboratories s-a început dezvoltarea unui nou sistem de operare pentru minicalculatoare, numit UNIX. O primă versiune a acestui sistem de operare a fost scrisă pentru minicalculatorul DEC – PDP7 în limbajul B (creat de Martin Richards) orientat pentru programare de sistem. UNIX se dorea să fie un sistem de operare portabil, scris în limbaj de nivel înalt, putând astfel să fie compilat și instalat pe orice tip de minicalculator, cu condiția să fie disponibil un compilator pentru limbajul de nivel înalt folosit. În 1972 pentru elaborarea unei noi versiuni UNIX, Dennis Ritchie pornind de la limbajul B îl dezvoltă creând limbajul C și compilatorul pentru DEC – PDP11. Odată cu răspândirea în mediul universitar a sistemului de operare UNIX și limbajul C devine din ce în ce mai cunoscut și folosit ca instrument de dezvoltare a UNIX. În prezent compilatorul limbajului C este disponibil pe toate tipurile de calculatoare ceea ce permite scrierea de aplicații portabile mai ales dupa ce în 1983 limbajul a fost standardizat de American National Standards Committee on Computers and Information Processing. În 1989 standardul este aprobat de ANSI în cooperare cu ISO (International Standards Organization)(ANSI C).
În 1980, tot la Bell Laboratories, Bjarne Stroustrup extinde limbajului C adăugându-i facilități necesare programării orientate pe obiecte. Noua versiune a limbajului este numita C++.
Conceptul de programare orientată pe obiecte revoluționează tehnologia de elaborare a programelor. Obiectele sunt componente software refolosibile, modelând obiectele din lumea reală. În această abordare programele se construiesc cu ajutorul acestor componente ca într-un joc cu cuburi. Lucrul în echipă la proiectarea și dezvoltarea programelor folosind aceste componente modulare este mult mai productivă decat în cazul folosirii tehnologiilor utilizate anterior (modularitate, programare structurată). C++ permite scrierea programelor atât în stilul C clasic cât și în stilul orientat pe obiecte. Ulterior au apărut și alte limbaje de programare orientată pe obiecte cum ar fi Smaltalk elaborat de Xerox Palo Alto Research Center (PARC) și limbajul Java elaborat de Sun. Practic toate sistemele de operare apărute după 1972 au fost scrise în C/C++.
Istoricul și caracteristicile limbajului Java[1]
Java este un limbaj de programare orientat obiect, destinat în principal programarii Internet.
Începutul limbajului java este în toamna anului 1991, când firma Sun Microsystem a finanțat un proiect cu numele Green condus de James Gosling. Scopul echipei Green era să plaseze firma Sun Microsystrm pe piața produselor electronice comerciale. Inginerii și dezvoltatorii de soft de la Sun au căutat microprocesoare care să ruleze pe o multitudine de mașini, în particular pe sisteme distribuite care lucrează în timp real. Cheia succesului firmei Sun a fost abilitatea lucrului pe platforme multiple. După patru ani de lucru, echipa Green finalizează specificatiile limbajului Java. Apoi, compania Sun Microsystem vinde licența firmelor IBM, Microsoft, Silicon Graphics, Adobe și Netscape.
Caracteristicile limbajului Java sunt:
Limbaj interpretat și compilat. Un limbaj este interpretat dacă instrucțiunile unui limbaj scris în acel limbaj sunt procesate linie cu linie și traduse în cod mașina. Un limbaj este compilat dacă un program scris în acel limbaj este tradus într-un cod pe care calculatorul îl poate “înțelege” (executa) mult mai ușor. Programele interpretate sunt mai lente decât cele compilate, însă cele compilate sunt de obicei dependente de platform respective. Programele Java sunt mai întâi compilate în niște fișiere intermediare asemănătoare codului de asamblare (numite byte code, eng.), apoi acestea sunt interpretate de mediul de execuție Java în instrucțiuni mașină asociate platformei sistem.
Limbaj independent de platformă. La instalarea limbajului Java, se va creea o mașină virtuală Java care are ca scop traducerea instrucțiunilor unui byte code Java în instrucțiuni mașină pentru platforma curentă. Astfel fișierele intermediare byte code pot fi copiate și executate pe orice platform (indiferent că aceasta este Windows, Unix, Solaris etc.) .
Limbaj orientat obiect. Cea mai importantă proprietate a limbajului Java este orientarea obiect, aceasta fiind privită ca o trăsătură implicită. Java pune în evidență toate aspectele legate de programarea orientată obiect: obiecte, trimitere de parametri, încapsulare, clase, biblioteci, moștenire și modificatori de acces.
Limbaj concurent. Concurența înseamnă capacitatea unui program de a executa mai multe secvențe de cod în acelaș timp. O secvență de cod Java se numește fir de execuție. Datorită posibilității creării mai multor fire de execuție, un program Java poate să execute mai multe sarcini simultan (de exemplu: animația unei imagini, transmiterea unei melodi spre placa de sunet, comunicarea cu un server, alocarea și eliberarea memoriei etc.).
Limbaj simplu. Spre deosebire de C++, care este cel mai popular limbaj orientat obiect, Java elimină câteva din trăsăturile acestuia: posibilitatea moștenirii multiple este exclusă, șirurile sunt încapsulate într-o structură clasă. Spre deosebire de C/C++, în Java nu există pointeri, iar alocarea și dealocarea memoriei se fac automat. Există un mecanism de elaborare a memorieipus în practică de un fir de execuție de prioritate mică.
Limbaj distribuit. Java este distribuit deoarece permite utilizarea obiectelor locale și de la distanță. Limbajul Java oferă posibilitatea dezvoltării de aplicații pentru Internet, capabile să ruleze pe platforme distribuite și eterogene. În acest sens, Java respectă standardul IEEE (eng. Institute of Electrical and Electronics Engineers) pentru structurile de date, cum ar fi folosirea întregilor, numerelor în virgula flotantă și șirurile de caractere. Java se poate utiliza în aplicații de rețea, cum ar fi FTP, HTTP etc.
Limbaj performant. Interpretorul Java este capabil să execute un byte code aproape la fel de repede ca un cod compilat. Având posibilitatea să lucreze cu fire de execuție multiple, Java justifică faptul că este un limbaj performant. De exemplu, un program Java poate aștepta citirea unor date, în timp ce un alt fir de execuție poate aloca sau elibera memoria necesară programului.
Limbaj dinamic și robust. Java întârzie alocarea obiectelor și legarea dinamică a claselor pentru momentul execușiei. Astfel, se vor evita erorile de alocare chiar dacă mediul s-a schimbat de la ultima compilare a programului. Faptul ca Java este robust se justifică prin eliminarea utilizării pointerilor, care erau generatoare de erori în cazul programelor C/C++. În schimb, Java verifică memoria dinamic înainte de a fi alocată și are un sistem automat de alocare/dealocare a memoriei.
Limbaj sigur. Programele Java nu pot accesa memoria heap, stack sau alte secțiuni protejate de memorie, deoarece Java nu folosește pointeri și alocă memorie doar la execuție. Înainte ca interpretorul Java să execute byte codul, se verifică dacă este un cod Java valid prin cercetarea accesului la date, conversiilor de date nepermise, valori și parametri incorecți, depășirea stivei.
Java vizavi de C/C++[2]
Sintaxa Java este asemănătoare, în mare parte, cu cea a limbajelor C și C++. În continuare o să încerc să prezint o paralelă între Java și C/C++. Voi descrie o sumă de deosebiri și cateva asemănări dintre ele și voi prezenta elemente care sunt în Java și nu sunt in C++ și elemente care au ramăs în C++, dar din Java au fost eliminate.
Tipuri de date
Tipurile de date primare
În Java sunt 8 tipuri de date primare, prezentate în tabelul de mai jos:
Se observă că Java mai adaugă două tipuri de date: byte și boolean. (o parte din compilatoare de C++ mai noi au adăugat și ele tipul boolean).
O importantă diferență privind celelalte tipuri de date, care sunt comune ambelor limbaje, este faptul că tipurile Java au o dimensiune cunoscută și fixă. Datorită scopului său de a fi portabil acest lucru este foarte important pentru Java. De exemplu, dacă un tip de dată int ocupă 16 biți pe o platformă și 32 de biți pe altă platformă, programul va întâmpina probleme dacă va trebui să ruleze pe ambele platforme. C++ garantează o anumită relație între tipurile primare de date, de exemplu garantează că un tip de dată long este cel puțin la fel de mare cu un tip de dată int. Însă el nu garantează dimensiunea fiecarui tip. Însă Java realizează acest lucru, fiecare tip având o dimensiune fixă.
Deoarece marea majoritate a mașinilor rulează pe 32 de biți, dimensiunile pentru tipurile primitive de date au fost găndite să fie optimizate pentru 32 de biți. Astfel, o dată Java de tip int ocupă 32 de biți (față de 16 sau 32 de biți, în C/C++), iar o dată de tip long va ocupa 64 de biți (față de 32 sau 64 de biți, în C/C++).
O altă diferență este că toate tipurile de date primare din Java sunt cu semn. Din această cauză declaratiile unsigned din C nu sunt permise în Java.
Conversii
Atât în Java cât și în C++ se poate face conversie dintr-un tip de dată în altul. Dar în Java nu există conversii implicite.
Să luăm ca exemplu urmatoarea secvență de program scrisă în C:
long LongNumber = 32768;
int IntNumber;
IntNumber = LongNumber;
Compilatorul C/C++ va efectua o conversie implicită (cast) din tipul long în int. Pe o platformă de 16 biți (unde long are o lungime de 32 de biți și int are o lungime de 16 biți), în urmă conversiei, variabila IntNumber va avea valoarea 0. Astfel va avea loc o pierdere de precizie, fară ca programatorul să fie avizat.
Java elimină riscul unor potentiale erori în programare, referitoare la conversii, prin faptul că nu realizează conversii automate. Din această cauză programatorul este nevoit să facă o conversie explicită (de exemplu IntNumber = (int)LongNumber;).
Operatori
Operatorii din Java sunt aproximativ identici cu cei din C/C++. Acestia sunt următorii: “!” (negatie), “&&” (și condițional), “||” (sau condițional), “?:” (condiție). O diferență este că în Java acestia operează cu valori booleene. Astfel următoare secvență C:
int y = 4;
int z = 5;
if (y && z) {
//secventa de cod
}
va fi ilegală în Java, pentru că, așa cum spuneam anterior, nu se face conversie automată. Condiția va trebui deci scrisă explicit: if (y!=0 && z!=0).
O altă diferență privind operatorii, și care este de o importanță deosebită, este faptul că în Java operatorii nu pot fi supraincarcați, așa cum pot fi în C++. Folosirea acestei trăsături în C++ a produs crearea multor erori. Din această cauză dezvoltatorii Java au hotărât să nu păstreze această caracteristică.
Pointeri
Pointerii reprezintă în C++ un element care oferă programatorului multă flexibilitate. Cu toate acestea, folosirea pointerilor devine o importantă sursă de erori. Java nu permite programatorului să folosească pointeri de nici un fel.
În C++ programatorul are libertatea să transmită variabilele cum consideră că este mai bine folosind operatorii “&”, “*” și “->”. Însă în Java nu există acești operatori, dar există urmatoarea regulă: tipurile de date primare sunt transmise prin valoare (prin copierea efectivă), iar obiectele și masivele sunt transmise prin referință (prin copierea adresei).
Să luăm urmatorul exemplu: să se creeze o funcție care să returneze media unui student:
void medieStudent (int note[], double medie){
int suma=0;
for(int i=0;i<10;i++)
suma+=note[i];
medie=suma/10;
}
Rezultatul nu poate fi transmis ca parametru (și anume în variabila medie), pentru că acesta este transmis prin valoare si modificarea sa în interiorul funcției nu afectează variabila medie. În C acest parametru trebuia transmis prin adresă (int *medie sau int &medie). Prin urmare este necesară căutarea unei soluții de transmitere a parametrului prin adresă. Acest lucru se poate realiza prin crearea unei clase care să conțină variabila medie. Un obiect al acestei clase noi va fi transmis prin adresă ca parametru:
public class definesteStudent {
double medie;
}
iar funcția de mai sus va avea forma:
void medieStudent (int note[], definesteStudent stud){
int suma=0;
for(int i=0;i<10;i++)
suma+=note[i];
stud.medie=suma/10;
}
Bineînțeles că returnarea mediei, în cazul de mai sus, se putea face și ca return al funcției:
double medieStudent (int note[]) {…}
dar în cazul în care se dorește returnarea mai multor valori primare, singura soluție valabilă rămâne crearea unei clase care să le conțină.
Copierea obiectelor
Deoarece fiecare obiect este de fapt o referință, asignarea unui obiect altuia nu copiază decât adresa către care acesta referă.
Spre exemplu:
Button butonDa = new Button("Da");
Button butonNu = new Button("Nu");
butonOK = butonCancel;
Obiectul butonDa va fi o referință către obiectul referit de butonNu, iar obiectul care era alocat inițial în butonDa se pierde.
Pentru a copia datele efectiv dintr-un obiect în altul se folosește funcția clone(), disponibilă în clasele care implementează interfața Cloneable (cele mai multe dintre clasele standard):
butonDa=butonNu.clone();
Același lucru este valabil și pentru masive. Pentru a copia efectiv valorile unui vector in alt vector (de exemplu), fie trebuie copiată fiecare valoare în parte, fie trebuie folosită metoda System.arraycopy().
Verificarea egalității obiectelor
O altă implicare directă a faptului că obiectele sunt transmise prin referință il prezintă faptul că operatorul “==” verifică dacă două variabile referă către același obiect și nu dacă cele două variabile conțin aceleași valori. Un număr de clase definește metoda equals() în acest scop.
De exemplu:
String sirul1="abc";
String sirul2="123";
if(sirul1.equals(sirul2))
{…}
Null
Pentru variabilele de tip referință (obiecte și masive) valoarea implicită este null. Acesta este un cuvânt rezervat care înseamnă că această variabilă nu referă nici un obiect sau masiv. Spre deosebire de NULL din C, în Java “null” este un cuvânt rezervat care este doar o constantă predefinită cu 0.
Distincția dintre transmiterea prin referință și transmiterea prin valoare în Java este foarte importantă. Pentru înțelegerea acestei diferențieri urmatoarele elemente sunt foarte importante:
toate masivele (arrays) și obiectele sunt transmise prin referință;
toate tipurile primare de date sunt transmise prin valoare;
operatorii == și = consideră referințe la obiecte. Funcțiile equals() si colone() trebuiesc folosite pentru testarea obiectelor respective sau copierea efectivă;
referirea și dereferirea obiectelor și masivelor sunt realizate automat de Java;
referința nu poate fi convertită într-un tip primar de dată și nici invers;
nu există pointer în Java;
null este o valoare specială care indică absența unei referințe.
Limbajul Java a fost mult simplificat prin eliminarea pointerilor. Un beneficiu al eliminarii lor este și asigurarea unei securități mai bune a programelor (o caracteristică definitorie a limbajului Java). Astfel, prin eliminarea abilității programatorului de a folosi adrese direct din memoria sistemului, limbajul previne într-o oarecare măsură posibilitatea de a putea fi folosit deliberat în scopuri periculoase de gen viruși, buffer overflow, stack overflow.
Gestionarea automata a memoriei
Aceasta este una dintre trăsăturile care face limbajul Java renumit pentru ușurința programării. Deși operatorul new alocă memorie pentru un obiect, nu există un operator corespondent care să dezaloce memoria alocată anterior prin new. Colectorul de gunoaie eliberează un spațiu de memorie imediat ce nu mai există o referință către acesta.
De exemplu: să presupunem că am folosit o culoare pentru desenarea unui background:
Color background = new Color(250,250,250);
În memorie se alocă un spațiu pentru acest obiect, care are adresa background.
Mai târziu vrem să schimbam culoarea, și procedam astfel:
background = new Color(0,0,0);
Acum un nou obiect este alocat, iar adresa acestuia este trecută în variabila background. Prin urmare obiectul alocat anterior nu va mai fi referit, în concluzie memoria va fi dezalocată automat.
Această facilitate scutește programatorul să țină cont de toate obiectele alocate, sporindu-i rapiditatea programării și eliminând din erori.
Clase
Modelul orientat pe obiecte din Java a fost inspirat din limbajul C++. Dar deși clasele în C++ sunt importante, în Java sunt obligatorii și sunt "centrul lucrurilor". În Java nu există variabile sau funcții de sine-stătătoare. Totul trebuie încapsulat într-una sau mai multe clase. În plus, există o întreagă ierarhie de clase, care are ca "strămoș" comun clasa Object.
Regăsim în clasele Java modificatorii public, protected și private. Ei au aceeași semnificație ca și în C++. În plus, Java mai are un al patrulea nivel de acces, care este folosit implicit. Dacă nu este specificat nici un modificator, atunci membrul respectiv este accesibil în cadrul pachetului în care clasă este definită, dar nu și în altă parte. Codul Java este vizibil la nivelul pachetului, iar un pachet conține definițiile și implementările de cod a uneia sau mai multor clase.
Funcțiile Membre
În Java fiecare metoda are corpul în același loc unde are și definiția. De aceea Java nu are nevoie de cuvântul cheie inline din C++. Toate metodele sunt scrise ca și funcțiile inline din C++.
Valori implicite ale variabilelor
Alt element care aduce o îmbunatatire în Java în comparative cu C++ este abilitatea de a seta o valoare implicită pentru o variabilă membră la momentul declarării ei.
Spre exemplu:
class Persoana {
protected int varsta = 20;
}
În C++, această atribuire se putea face numai în constructor. În Java posibilitatea atribuirii unei valori implicite are avantajul că dacă există mai mulți constructori care trebuie să aloce aceeași valoare unei variabile, aceștia sunt simplificați pentru că nu mai este necesară scrierea lor.
Constructori și destructori
În Java fiecare clasă poate include unul sau mai multi constructori. Ca și în C++, constructorul are același nume ca și clasa. Constructorii în Java nu returnează nici o valoare și sunt declarați în același mod ca și celelalte metode.
În C++ era nevoie de destructori pentru a elibera memoria alocată de un obiect. Deoarece Java include "colectorul de gunoaie" pentru eliberarea automată a memoriei care nu mai este referită, existența destructorilor nu mai este necesară. Din această cauză destructori din C++ nu există, fiecare clasă Java poate include în schimb metoda finalize, care realizează eliberarea obliectului. Funcția este definită în clasa Object, deci este moștenită de toate clasele.
Moștenirea
Mostenirea în Java este indicată prin folosirea cuvântului cheie “extends”. Ca și C++, Java include cuvântul “this” care poate fi folosit de un obiect pentru a se referi pe sineînsuși. În plus, Java include și cuvântul cheie “super” pe care un obiect sau o clasă il poate folosi pentru a referi o metodă din clasa părinte.
Exemplu:
class Persoana {
String nume;
String prenume;
Persoana(String n, String p) {
nume = n;
prenume = p;
}
}
class Student extends Persoana {
String facultate;
Persoana(String n, String p, String f) {
super(n,p);
facultate = f;
}
}
Pe scurt: o clasă poate moșteni o singură altă clasă, însă poate implementa mai multe interfețe. O interfață este o clasă care are numai metode abstracte, deci corpul lor trebuie definit în clasele care o moștenesc.
Lipsa preprocesorului
C și C++ includ directivele #define, #include, și #ifdef. Java nu include nici un fel de preprocesor.
Definirea constantelor
Orice variabilă declarată final este constantă. Valoarea sa trebuie specificata de la inițializare și ea nu poate fi schimbată ulterior. Echivalentul directivei #define din C este o variabila declarată static final.
De exemplu variabila PI din clasa java.lang.Math este definita astfel:
public static final double PI = 3.14159…
Macrouri
Java nu are un echivalent pentru macrourile din C, dar tehnologia compilatoarelor a avansat destul de mult încat să nu mai fie nevoie de ele.
Includerea fișierelor
Java are directiva import, care este aproximativ similară cu directiva #include din C. Directiva import spune compilatorului că fișierul curent folosește clasele specificate sau clasele din pachetele specificate și permite programatorului să folosească nume scurte (de exemplu Math.PI în loc de java.lang.Math.PI).
Compilarea condiționată
Java nu are directivele #ifdef și #if pentru a realiza compilarea condiționată. Teoretic, compilarea condiționată nici nu ar trebui să fie necesară în Java, deoarece aceasta se folosește de obicei la schimbarea platformei. Practic însă, compilarea condiționată este folositoare și în Java, de exemplu pentru a crea interfețe puțin diferite în funcție de platformă sau pentru a include cod pentru debug.
Compilatorul Java realizează implicit o compilare condiționată, în sensul că nu va compila un cod care în mod evident nu va fi executat. Compilarea condiționată funcționează și cu constante (cu variabile declarate static final).
Acestea se folosesc în general pentru debug. Dacă o clasă definește o astfel de constantă astfel:
private static final boolean DEBUG = false;
atunci compilatorul nu va compila cod de genul if(DEBUG). Pentru activarea opțiunii de debug, este necesară doar schimbarea valorii constantei și recompilarea codului.
Alte diferențe
În afară de cele menționate, mai există un număr de alte diferențe, pe care le voi enumera pe scurt în continuare:
Variabile multidimensionale
Ca si C/C++, Java foloseste parantezele patrate pentru a declara un masiv. Sunt insa doua diferente:
in Java parantezele pot fi plasate fie inaintea, fie dupa numele variabilei;
dimensiunea masivului nu trebuie specificata intre paranteze la momentul declararii variabilei. Acest lucru nu este necesar si nici permis pentru ca Java cere ca toate masivele sa fie alocate folosind operatorul new:
int vector[];
vector = new int[100];
sau
int vector[] = new int[100];
Comentarii
In afara de comentariile existente si in C/C++, si anume: // si /*…*/, Java introduce un nou tip de comentariu: /**…*/ Un astfel de comentariu poate fi extras din codul sursa si folosit pentru a crea documentatie pentru clasa respectiva cu utilitaruljavadoc. Acest mod de comentare a codului este folosit pentru toate clasele standard din Java.
Argumente in linia de comanda
Unui program C sau C++ i se pot transmite argumente in linia de comanda cu ajutorul parametrilor argc si argv, unde argc reprezinta numarul de parametri transmisi, iar argv este un sir cu parametrii respectivi. Intotdeauna va fi cel putin un parametru transmis, deoarece primul parametru este numele programului:
main ( int argc, char *argv[] )
Intr-o aplicatie Java ( intr-un applet nu putem vorbi despre functia main), argumentele din linia de comanda sunt trecuti intr-un sir de obiecte de tip String:
public static void main(String args[]);
Fiecare componenta a sirului args este un parametru transmis. Diferenta fata de C/C++ este ca in Java numele programului nu este transmis ca parametru.
Goto, break si continue
Cuvantul cheie goto nu este folosit in Java. El este pe lista cuvintelor rezervate, asa ca poate la un moment dat o sa se revina asupra lui. Exista insa doi substituenti pentru goto: break si continue pot fi folosite cu etichete. Break si continue au si valoarea cunoscuta din C, dar au in plus si facilitatea de "goto":
eticheta:
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
if(x[i]<10)
break eticheta;
else if(x[i]>100)
continue eticheta
}
}
Synchronized
Fiind un sistem multithreading, Java trebuie sa previna ca mai multe fire de executie sa modifice simultan acelasi obiect. Sectiunile de cod care nu trebuie executate simultan sunt denumite "sectiuni critice". Java furnizeaza cuvantul cheie synchronized pentru a proteja aceste sectiuni critice.
Package si import
Java furnizeaza de asemenea cuvantul cheie package pentru a specifica pachetul din care clasa respectiva face parte. Clauza import are acelasi rol cu #include din C.
Elemente care lipsesc in Java
Sunt o suma de alte elemente care exista in C++ si nu exista in Java. Printre acestea enumar: templates, functii friend, parametri impliciti, struct, union. In cele mai multe cazuri insa, nici nu este nevoie de ele, sau ele pot fi inlocuite prin altceva. Eliminarea lor este justificata de faptul ca simplifica mult crearea programelor Java.
Ca o concluzie, Java a fost conceput sa ajute programatorul cat mai mult prin usurinta programarii, lasand greul in seama Java. Intr-adevar, fata de C++, Java este mult mai usor, mai ales ca au fost dezvoltate clase pentru aproape toate tipurile de aplicatii. Raman insa tipuri de programe care nu pot fi facute in Java, programarea lor in C/C++ fiind mult mai eficienta. Aceasta datorita libertatii accesului la resurse, vitezei de executie mult mai mari (stiti ca Java este jumatate interpretat) etc.
Prin urmare avantaje si dezavantaje raman de ambele parti, numai tipul aplicatiei si programatorul poate decide ce limbaj sa aleaga.
CAPITOLUL 2 : GENERALITĂȚI
Mediul de dezvoltare a aplicațiilor Java[4]
Programele Java parcurg cinci faze de dezvoltare: editare, compilare, încărcare, verificare și execuție.
Schematic aceste etape pot fi reprezentate ca în figura 1.1. Prima fază constă în editarea programului folosind un editor de text (cum ar fi Notepad-ul din Windows sau vi –ul din UNIX). Programul sursă va fi salvat într-un fișier cu extensia java (de exemplu prg1.java)
În a doua fază programul java este compilat folosind comanda javac (de exemplu javac prg1.java) pentru a lansa compilatorul. Acesta “traduce” programul sursă în cod binar (byte code) – limbaj înțeles de interpretor. Acest cod intermediar este salvat într-un fișier cu extensia class (de exemplu prg1.class).
Faza a treia constă în amplasarea codul binar din fișierul class în memorie de către încărcător. Încărcarea se poate face de pe discul local sau prin rețea. Există doua tipuri de programe java – aplicații și applet-uri. În cazul aplicațiilor java această operație este inițiată de comanda java (de exemplu java prg1). Appleturile sunt destinate execuției de către o mașină virtuală java implementată de un browser (de exemplu Internet Explorer sau Netscape Navigator) în cadrul unui document HTML (HyperText Markup Language). Un applet poate fi executat și local cu ajutorul programului appletviewer.
Figura 1.1 – mediul de dezvoltare al programelor Java
Interfețe[1]
O interfața gupează mai multe metode și date membre publice. Sunt definite doar prototipurile metodelor, implementările urmând a fi scrise în clasa care va implementa respectiva interfață. Gruparea metodelor publice este utilă pentru a da aceeași modalitate de lucru cu anumite clase. Există și interfețe care nu posedă metode sau date membre, acasta având rol de indicator.
O clasa poate implementa mai multe interfețe, dar poate moșteni doar o singura clasă. Relația de moștenire este valabila și pentru interfețe. Prin implementarea mai multor interfețe se simulează moștenirea multiplă (întâlnită in limbajul C++).
O declarație de interfață introduce un tip referință ai cărui membri sunt constante și metode abstracte. Acest tip nu posedă implementări (metodele nu sunt definite), dar anumite clase pot implementa aceste interfețe furnizând definiții pentru metodele abstracte. Sintaxa generală a declarației unei interfețe este:
[public | abstract] interface <Identificator> [extends <ListaInterfete>] {
[<DeclatatiiMembriInterfata>]
}
unde:
<Identificator> reprezintă numele interfeței;
<ListaInterfete> are forma generală: <Interfata1>,…,<InterfataN>, unde <InterfataI> reprezintă identificatori (nume) de interfețe, pentru I de la 1 la N;
<DeclatatiiMembriInterfata> are forma generală: <DeclaratieMembru1> ,…, <DeclaratieMembruK>, unde <DeclaratieMembruI> , pentru I de la 1 la K, poate fi: <DeclaratieConstanta> sau <DeclaratieMetodaAbstracta>.
Numele unei interfețe (<Identificator>) nu poate coincide cu numele altei clase sau interfețe din același pachet, altfel apare eroare la compilare. Ca și în cazul claselor, domeniul numelui unei interfețe este intreg pachetul în care este declarat. Fiecare interfață este implicit abstractă, deci este considerat învechit modificatorul abstract în declarația unei interfețe.
Dacă declarația unei interfețe conține clauza extends, atunci interfața va moșteni toate metodele și constantele interfețelor enumerate în <ListaInterfete>, care se numesc superinterfețe directe. Orice clasă care implementează interfața declarată va trebui să implementeze toate superinterfețele accesibile clasei.
Suprinterfețele din clauza extends trebuie să fie accesibile, altfel apare eroare la compilare. Nu există o super interfață generală (pentru toate interfețele), cum este clasa Object pentru superclase.
Membrii unei interfețe sunt acei membri moșteniți din superinterfețele directe și acei membri declarați în interfață. Interfața moștenește toți membrii superinterfețelor, cu excepția atributelor ascunse și a metodelor suprascrise. Domeniul numelui unui membru declarant intr-un tip interfață este corpul declarației interfeței. Toți membrii unei interfețe sunt implicit public. Astfel, dacă membrii sunt declarați public, atunci aceștia sunt accesibili și în afara pachetului.
Declarațiile atributelor unei interfețe
Atributele unei interfețe sunt de fapt constante și au sintaxa generală:
[public I static I final] <Tip> <DeclaratieVariabilal> [, …, I <DeclaratieVariabilaN>];
unde:
modificatorii public, static și final sunt impliciți și specificarea’lor este redundantă;
<DeclaratieVariabilaI>, cu I = 1, …, N, poate fi:
E<Identificator> = <InitializatorVariabila> sau
cidentificator> [] [ []…[] ]= <InitializatorTablou>;
Spre deosebire de clasă, declarația uinui atribut într-o interfață nu poate conține modificatorii synchronized, transient sau vblatile.
Fiecare atribut din corpul unei interfețe trebuie să aibă o expresie de inițializare, care nu este obligatoriu să fie constantă. Inițializatorul variabilei este evaluat și asignarea are loc o singură dată, când se inițializează interfața. O expresie de inițializare nu poate conține o referință prin nume simplu la același atribut sau la alt atribut a cărui declarație apare mai târziu în aceeași interfață. La fel, dacă expresia de inițializare conține cuvintele rezervate this sau super, atunci apare o eroare la compilare.
Este posibil pentru o interfață să moștenească mai multe atribute cu același nume de la mai multe interfețe, însă încercarea de a ne referi cu nume simplu la un astfel de atribut conduce la eroare de compilare deoarece referința este ambiguă.
Dacă două atribute cu același nume sunt moștenite de o interfață, atunci se obține ambiguitatea atributului. Această situație poate apărea, de exemplu, când două super- interfețe directe declară acest atribut. încercarea de accesare a acestui atribut conduce la eroare de compilare. Evident, este posibilă accesarea folosind nume calificat (numele interfeței dorite).
Invers, o altă situație este când un singur atribut este moștenit de mai multe din aceeași interfață (se mai numește moștenire multipla). Această situație se poate obține, de exemplu, când ințerfața iOește superințerfață pentru alte două noi interfețe I1 și I2, care la rândul lor sunt superinterfețe pentru o altă interfață I3. Astfel, atributele din interfața I0 sunt moștenite de mai multe ori, însă se păstrează doar o singură copie, deci accesarea acestora nu determină eroare la compilare.
Declarațiile metodelor unei interfețe
Metodele unei interfețe sunt asemănătoare cu metodele unei clase, cu excepția faptului că structura <CorpMetodă> este ; și că nu permit apariția tuturor modificatorilor de clasă. Spre deosebire de metodele unei clase, declarația unei metode într-o interfață nu poate conține modificatorii static, final, synchronized sau native. Sintaxa generală a declarației metodei unei interfețe este:
[public I abstract] <TipRezultat> cidentificator> ;
([<ListaParametriFormali>])
throws <TipClasal> [, …, <TipClasaN>];
unde:
modificatorii public și abstract sunt impliciți și specificarea lor este redun¬dantă;
<ldentif icator> reprezintă numele metodei.
Declarația unei metode suprascrie toate metodele cu aceeași signatură din super- interfețele sale care sunt accesibile codului interfeței. In acest caz, acestea trebuie să întoarcă același tip, și dacă au clauze throws, nu trebuie să intre în conflict. Astfel, o interfață moștenește toate metodele ne-suprascrise ale superinterfețelor sale. Metodele declarate în interfețe sunt abstracte și deci nu au implementare. Cum metodele suprascrise au aceeași signatură (și compilatorul le forțează să returneze același tip), înseamnă că singurul loc unde pot să difere este în lista de excepții care pot fi aruncate de metoda suprascrisă (eventual restrângând lista acestora).
Dacă două metode ale unei interfețe (declarate în aceeași interfață sau moștenite) au același nume, dar diferite signaturi, atunci spunem că numele metodei este supra-încărcat.
Crearea interfețelor grafice cu pachetul Swing
Utilizarea componentelor Swing
Pachetul swing conține două tipuri de componente:
containere (JFrame, JApplet, JWindow, JDialog)
componente "lightweight" (JButton, JPanel, JList etc. )
Containerele reprezintă cadrul în care aceste componente pot exista. Imaginea urmatoare prezintă ierarhia componentelor unei aplicații cu o fereastră, două butoane, o casetă text și o listă.
Obiectul contentpane din figura precedentă este un obiect Container obișnuit și este sub containerul swing.
Observație: Nu se pot adăuga componentele direct la containerul swing.
Figura urmatoare conține câteva componente împreună cu ierarhia de clase în care se încadrează:
JLabel
Un JLabel este similar cu o eticehtă java.awt.Label, având o serie de funcționalități în plus:
permite atașarea unei iconițe
permite poziționarea verticală și orizontală a textului față de iconiță
permite poziționarea relativă a conținutului în cadrul componentei
Exemplul următor utilizează interfața Icon:
public interface Icon{
void paintIcon( Component c, Graphics g, int x, int y );
int getIconWidth();
int getIconHeight();
}
Clasa ImageIcon este o implementare a clasei Icon, care crează o iconiță dintr-un obiect de tip Image.
Icon iconPicture = new ImageIcon("Apple.gif");
Un exemplu:
În toate exemplele demonstrative pentru componente se vor utiliza doua clase. O clasa care extinde clasa JPanel și care conține componenta specifică și una de tip container care extinde clasa JFrame și afisează panelul cu componentele specifice. De aceea în cazul urmatoarelor exemple vom descrie doar constructorul clasei SwingPanel.
JButton
Un buton JButton se instanțiează analog ca și un buton java.awt.Button. Evenimentul care se produce la apasarea acestuia este tot un ActionEvent și evenimentul se livrează tuturor receptorilor inregistrați. Culoarea butonului este identică cu culoarea containerului, deci trebuie modificată la SystemColor.control.
setLayout( new FlowLayout() );
JButton simplebutton = new JButton("Simple");
add( simplebutton );
simplebutton.setBackground(SystemColor.control);
Icon icon = new ImageIcon("icon.gif");
JButton iconbutton = new JButton("Icon", icon );
iconbutton.setBackground(SystemColor.control);
add( iconbutton );
JTextComponent
JTextComponent este o clasă generală cu toate funcțiunile unui editor de text simplu. Metodele cele mai utilizate:
copy()
cut()
paste()
getSelectedText()
setSelectionStart()
setSelectionEnd()selectAll()
replaceSelection()
getText()
setText()
setEditable()
setCaretPosition()
Subclasele clasei JTextComponent sunt: JTextField, JTextArea, JTextPane.
setLayout( new BorderLayout());
JTextPane tp = new JTextPane();
MutableAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setFontFamily(attr,"Serif");
StyleConstants.setFontSize(attr,18);
StyleConstants.setBold(attr,true);
tp.setCharacterAttributes( attr, false );
add( tp, BorderLayout.CENTER );
JPasswordField
JPasswordField este subclasa clasei JTextField. Cu metoda setEchoChar() se poate specifica caracterul care se afișează în locul caracterelor introduse. Implicit este '*'.
setLayout( new FlowLayout() );
JPasswordField pf = new JPasswordField(20);
pf.setEchoChar('*');
add(pf );
JScrollBar
JScrollBar este varianta "lightweight" a componentei java.awt.Scrollbar.
setLayout( new BorderLayout() );
JScrollBar vertical = new JScrollBar(JScrollBar.VERTICAL,0,5,0,100);
add(vertical, BorderLayout.EAST );
JScrollBar horizontal = new JScrollBar(JScrollBar.HORIZONTAL,0,5,0,100);
add(horizontal, BorderLayout.SOUTH );
JSlider
JSlider este similar cu JScrollBar, dar permite afisarea marcjelor minore respectiv a celor majore precum și desenarea unui chenar Border în jurul componentei.
setLayout( new BorderLayout() );
JSlider s1 = new JSlider( JSlider.VERTICAL, 0, 100, 50 );
s1.setPaintTicks( true );
s1.setMajorTickSpacing(10);
s1.setMinorTickSpacing(2);
add( s1, BorderLayout.EAST);
JSlider s2 = new JSlider( JSlider.VERTICAL, 0, 100, 50 );
s2.setPaintTicks( true );
s2.setMinorTickSpacing(5);
add( s2, BorderLayout.WEST);
JSlider s3 = new JSlider( JSlider.HORIZONTAL, 0, 100, 50 );
s3.setPaintTicks( true );
s3.setMajorTickSpacing(10);
add( s3, BorderLayout.SOUTH);
JSlider s4 = new JSlider( JSlider.HORIZONTAL, 0, 100, 50 );
s4.setPaintTicks( true );
s4.setBorder( LineBorder.createBlackLineBorder());
add( s4, BorderLayout.NORTH);
JProgressBar
JProgressBar se utilizează pentru vizualizarea evoluției unei operații. Pentru a lucra cu o asemenea componentă prima dată trebuie s-o inițializăm.
JProgressBar p = new JProgressBar();
p.setMinimum( 0 );
setMaximum( numar_operatii );
iar după aceea într-un ciclu să modificăm starea componentei
p.setValue( p.getMinimum());
for( int i=0; i<numar_operatii; i++)
{
//se executa o operatie
p.setValue( i );
}
JComboBox
Componenta JComboBox este asemănătoare cu Choice din AWT, dar permite și editarea, adică introducerea unei valori care nu există în listă.
Exemplu de utilizare:
Sursa:
public class SwingPanel extends JPanel
{
String elements[] ={"One","Two","Three","Four","Five"};
public SwingPanel()
{
setLayout( new FlowLayout() );
JComboBox c1 = new JComboBox();
JComboBox c2 = new JComboBox();
for( int i =0; i< elements.length; i++ )
{
c1.addItem( elements[ i ] );
c2.addItem( elements[ i ] );
}
c1.setEditable( false );
c2.setEditable( true );
add( c1 );
add( c2 );
}
}
JList
Componenta JList are două implementări -una care respectă arhitectura MVC și una care nu- se comportă la fel ca și o listă AWT. Totuși și această implementare mai simplă s-a imbunătațit. Putem adăuga elementele prin constructor transmițându-i un tablou de stringuri. JList nu suportă scroll, adică dacă dorim această facilitate atunci trebuie s-o punem intr-un ScrollPane.
import javax.swing.*;
import java.awt.*;
public class SwingPanel extends JPanel
{
String elements[] = {"Orange","Lemon","Strawberry","Raspberry","Apple","Banana"};
public SwingPanel()
{
setLayout( new BorderLayout() );
JList list = new JList(elements);
ScrollPane pane = new ScrollPane();
pane.add( list );
add( pane, BorderLayout.CENTER );
}
}
Timer
Pe langă componente grafice, pachetul swing vine și cu o serie de utilitare. Un astfel de utilitar este clasa Timer. Exemplul următor este o fereastră cu trei butoane și cu trei obiecte de tip Timer. Fiecare obiect Timer controlează un buton, adică la trecerea intervalului specific fiecărui timer se incrementează numarul de pe butonul corespunzător. La crearea obiectelor de tip Timer specificăm intervalul de timp la care actionează respectiv și obiectul listener, adică componenta care este notificată. Timerul trimite mesajul actionPerformed() după trecerea intervalului de timp. Obiectul Timer trebuie pornit cu metoda start().
Diagrama de clasa
Diagrama de secventiere
Lucrul cu baze de date[3]
Introducere
Generalități despre baze de date
Aplicațiile care folosesc baze de date sunt, în general, aplicații complexe folosite pentru gestionarea unor informații de dimensiuni mari într-o manieră sigură și eficientă.
Ce este o bază de date?
La nivelul cel mai general, o bază de date reprezintă o modalitate de stocare a unor informații (date) pe un suport extern, cu posibilitatea regăsirii acestora. Uzual, o bază de date este memorată într-unul sau mai multe fișiere.
Modelul clasic de baze de date este cel relașional, în care datele sunt memorate în tabele. Un tabel reprezintă o structură de date formată dintr-o mulțime de articole, fiecare articol având definite o serie de atribute – aceste atribute corespund coloanelor tabelului, în timp ce o linie va reprezenta un articol. Pe lânga tabele, o bază de date mai poate conține: proceduri și funcții, utilizatori și grupuri de utilizatori, tipuri de date, obiecte, etc.
Dintre producătorii cei mai importanți de baze de date amintim companiile Oracle, Sybase, IBM, Informix, Microsoft, etc. fiecare furnizând o serie întreagă de produse și utilitare pentru lucrul cu baze de date. Aceste produse sunt în general referite prin termenii DBMS (Database Management System) sau, în traducere, SGBD (Sistem de Gestiune a Bazelor de Date).În acest capitol vom analiza lucrul cu baze de date din perspectiva programării în limbajul Java, fără a descrie particularități ale unei soluții de stocare a datelor anume. Vom vedea că, folosind Java, putem crea aplicații care să ruleze fără nici o modificare folosind diverse tipuri de baze care au aceeași structură, ducând în felul acesta noțiunea de portabilitate și mai departe.
Crearea unei baze de date
Crearea unei baze de date se face uzual folosind aplicații specializate oferite de producătorul tipului respectiv de sistem de gestiune a datelor, dar există și posibilitatea de a crea o bază folosind un script SQL. Acest aspect ne va preocupa însă mai puțin, exemplele prezentate presupunând că baza a fost creată deja și are o anumită structură specificată.
Accesul la baza de date
Se face prin intermediul unui driver specific tipului respectiv de SGBD. Acesta este responsabil cu accesul efectiv la datele stocate, fiind legatura dintre aplicație și baza de date.
Limbajul SQL
SQL (Structured Query Language) reprezintă un limaj de programare ce permite interogarea și actualizarea informațiilor din baze de date relaționale. Acesta este standardizat astfel încât diverse tipuri de drivere să se comporte identic, oferind astfel o modalitate unitară de lucru cu baze de date.
JDBC
JDBC (Java Database Connectivity) este o interfață standard SQL de acces la baze de date. JDBC este constituită dintr-un set de clase și interfețe scrise în Java, furnizând mecanisme standard pentru proiectanții aplicațiilor ce folosesc de baze de date.
Folosind JDBC este ușor să transmitem secvențe SQL către baze de date relaționale. Cu alte cuvinte, nu este necesar să scriem un program pentru a accesa o bază de date Oracle, alt program pentru a accesa o bază de date Sybase și așa mai departe. Este de ajuns să scriem un singur program folosind API-ul JDBC și acesta va fi capabil să comunice cu drivere diferite, trimițând secvențe SQL către baza de date dorită. Bineînțeles, scriind codul sursă în Java, ne este asigurată portabilitatea programului. Deci, iată două motive puternice care fac combinația Java – JDBC demnă de luat în seamă.
Pachetele care oferă suport pentru lucrul cu baze de date sunt java.sql ce reprezintă nucleul tehnologiei JDBC și, preluat de pe platforma J2EE, javax.sql.
În linii mari, API-ul JDBC oferă următoarele facilități:
Stabilirea unei conexiuni cu o bază de date.
Efectuarea de secvențe SQL.
Prelucrarea rezultatelor obținute.
Conectarea la o baza de date
Procesul de conectare la o bază de date implică efectuarea a două operații:
Înregistrarea unui driver corespunzător.
Realizarea unei conexiuni propriu-zise.
Definiție
O conexiune (sesiune) la o bază de date reprezintă un context prin care sunt trimise secvențe SQL și primite rezultate. Într-o aplicație pot exista simultan mai multe conexiuni la baze de date diferite sau la aceeași bază.
Clasele și interfețele responsabile cu realizarea unei conexiuni sunt:
DriverManager – este clasa ce se ocupă cu înregistrarea driverelor ce vor fi folosite în aplicație;
Driver – interfața pe care trebuie să o implementeze orice clasă ce descrie un driver;
DriverPropertyInfo – prin intermediul acestei clase pot fi specificate diverse proprietăți ce vor fi folosite la realizarea conexiunilor;
Connection – descrie obiectele ce modelează o conexiune propriu-zisă cu baza de date.
Înregistrarea unui driver
Primul lucru pe care trebuie să-l facă o aplicație în procesul de conectare la o bază de date este să înregistreze la mașina virtuală ce rulează aplicația driverul JDBC responsabil cu comunicarea cu respectiva bază de date. Acest lucru presupune încărcarea în memorie a clasei ce implementează driver-ul și poate fi realizată în mai multe modalități.
Folosirea clasei DriverManager:
DriverManager.registerDriver(new TipDriver());
Folosirea metodei Class.forName ce apelează ClassLoader-ul mașinii virtuale:
Class.forName("TipDriver");
Class.forName("TipDriver").newInstance();
Setarea proprietății sistem jdbc.drivers, care poate fi realizată în două feluri:
– De la linia de comandă: java -Djdbc.drivers=TipDriver Aplicatie
– Din program: System.setProperty("jdbc.drivers", "TipDriver");
Dacă sunt înregistrate mai multe drivere, ordinea de precedent în alegerea driverului folosit la crearea unei noi conexiuni este:
Driverele înregistrate folosind proprietatea jdbc.drivers la inițializarea mașinii virtuale ce va rula procesul.
Driverele înregistrate dinamic din aplicație.
Specificarea unei baze de date
O dată ce un driver JDBC a fost înregistrat, acesta poate fi folosit la stabilirea unei conexiuni cu o bază de date. Având în vedere faptul că pot exista mai multe drivere încărcate în memorie, trebuie să avem posibilitea de a specifica pe lângă un identificator al bazei de date și driverul ce trebuie folosit. Aceasta se realizează prin intermediul unei adrese specifice, numită JDBC URL, ce are următorul format:
jdbc:sub-protocol:identificator
Câmpul sub-protocol denumește tipul de driver ce trebuie folosit pentru realizarea conexiunii și poate fi odbc, oracle, sybase, db2 și așa mai departe.
Identificatorul bazei de date este un indicator specific fiecărui driver corespunzător bazei de date cu care aplicația dorește să interacționeze. În funcție de tipul driver-ului acest identificator poate include numele unei mașini gazdă, un număr de port, numele unui fișier sau al unui director, etc., ca în exemplele de mai jos:
jdbc:odbc:test
jdbc:oracle:[anonimizat]:1521:test
jdbc:sybase:test
jdbc:db2:test
Subprotocolul odbc este un caz specical, în sensul că permite specificarea în cadrul URL-ului a unor atribute ce vor fi realizate la crearea unei conexiuni. Sintaxa completa subprotocolului odbc este: jdbc:odbc:identificator[;atribut=valoare]*
jdbc:odbc:test
jdbc:odbc:test;CacheSize=20;ExtensionCase=LOWER
jdbc:odbc:test;UID=duke;PWD=java
La primirea unui JDBC URL, DriverManager-ul va parcurge lista driverelor înregistrate în memorie, pâna când unul dintre ele va recunoaște URL-ul respectiv. Dacă nu exista nici unul potrivit, atunci va fi lansata o excepșie de tipul SQLException, cu mesajul "no suitable driver".
Realizarea unei conexiuni
Metoda folosită pentru realizarea unei conexiuni este getConnection din clasa DriverManager și poate avea mai multe forme:
Connection c = DriverManager.getConnection(url);
Connection c = DriverManager.getConnection(url, username, password);
Connection c = DriverManager.getConnection(url, dbproperties);
Stabilirea unei conexiuni folosind un driver MySql
Folosirea diferitelor tipuri de drivere implică doar schimbarea numelui clasei ce reprezintă driverul și a modalității de specificare a bazei de date.
String url = "jdbc:mysql://localhost/test" ;
// sau url = "jdbc:mysql://localhost/test?user=duke&password=java";
try {
Class.forName("com.mysql.jdbc.Driver") ;
} catch(ClassNotFoundException e) {
…
O conexiune va fi folosită pentru:
Crearea de secvențe SQL utilizate pentru interogarea sau actualizarea bazei.
Aflarea unor informații legate de baza de date (meta-date).
De asemenea, clasa Connection asigură facilități pentru controlul tranzacțiilor din memorie către baza de date prin metodele commit, rollback, setAutoCommit.
Inchiderea unei conexiuni se realizează prin metoda close.
Efectuarea de secvențe SQL
O dată facută conectarea cu metoda DriverManager.getConection, se poate folosi obiectul Connection rezultat pentru a se crea obiecte de tip Statement, PreparedStatement sau CallableStatement cu ajutorul cărora putem trimite secvențe SQL către baza de date. Cele mai uzuale comenzi SQL sunt cele folosite pentru:
Interogarea bazei de date: SELECT
Actualizarea datelor: INSERT, UPDATE, DELETE
Actualizarea structurii: CREATE, ALTER, DROP – acestea mai sunt numite instrucțiuni DDL (Data Definition Language)
Apelarea unei proceduri stocate: CALL
După cum vom vedea, obținerea și prelucrarea rezultatelor unei interogări este realizată prin intermediul obiectelor de tip ResultSet.
Interfața Statement
Interfața Statement oferă metodele de bază pentru trimiterea de secvențe SQL către baza de date și obținerea rezultatelor.
Crearea unui obiect Statement se realizează prin intermediul metodei createStatement a clasei Connection, fără nici un argument:
Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement();
Execuția unei secvențe SQL poate fi realizată prin intermediul a trei metode:
executeQuery
Este folosită pentru realizarea de interogări de tip SELECT. Metoda returnează un obiect de tip ResultSet ce va conține sub o formă tabelară rezultatul interogării.
String sql = "SELECT * FROM persoane";
ResultSet rs = stmt.executeQuery(sql);
executeUpdate
Este folosită pentru actualizarea datelor (INSERT, UPDATE, DELETE) sau a structurii bazei de date (CREATE, ALTER, DROP). Metoda va returna un întreg ce semnifică numărul de linii afectate de operațiunea de actualizare a datelor, sau 0 în cazul unei instrucțiuni DDL.
Execute
Această metodă va fi folosită doar dacă este posibil ca rezultatul unei interogări să fie format din două sau mai multe obiecte de tip ResultSet sau rezultatul unei actualizări să fie format din mai mule valori, sau o combinație între aceste cazuri. Această situație, deși mai rară, este posibilă atunci când sunt executate proceduri stocate sau secvențe SQL cunoscute abia la momentul execuției, programatorul neștiind deci dacă va fi vorba de o actualizare a datelor sau a structurii. Metoda întoarce true dacă rezultatul obținut este format din obiecte de tip ResultSet și false dacă e format din întregi. În funcție de aceasta, pot fi apelate metodele: getResultSet sau getUpdateCount pentru a afla efectiv rezultatul comenzii SQL. Pentru a prelua toate rezultatele va fi apelată metoda getMoreResults, după care vor fi apelate din nou metodele amintite, până la obținerea valorii null, respectiv −1.
Folosind clasa Statement, în cazul în care dorim să introducem valorile unor variabile într-o secvență SQL, nu avem altă soluție decât să creăm un șir de caractere compus din instrucțiuni SQL și valorile variabilelor:
int cod = 100;
String nume = "Popescu"; String sql = "SELECT * FROM persoane WHERE cod=" + cod + " OR nume=’" + nume + "’";
ResultSet rs = stmt.executeQuery(sql);
Interfața ResultSet
În urma execuție unei interogări SQL rezultatul va fi reprezentat printr-un obiect de tip ResultSet, ce va conține toate liniile ce satisfac condițiile impuse de comanda SQL. Forma generală a unui ResultSet este tabelară, având un număr de coloane și de linii, funcție de secvența executată. De asemenea, obiectul va conține și meta-datele interogării cum ar fi denumirele coloanelor selectate, numărul lor, etc.
Statement stmt = con.createStatement();
String sql = "SELECT cod, nume FROM persoane";
ResultSet rs = stmt.executeQuery(sql);
Rezultatul interogării de mai sus va fi obiectul rs cu următoarea structură:
cod nume
100 Ionescu
200 Popescu
Pentru a extrage informațiile din această structură va trebui să parcurgem tabelul linie cu linie și din fiecare să extragem valorile de pe coloane. Pentru acest lucru vom folosi metode de tip getXXX, unde XXX este tipul de dată al unei coloane iar argumentul primit indică fie numărul de ordine din cadrul tabelului, fie numele acestuia. Coloanele sunt numerotate de la stânga la dreapta, începând cu 1. În general, folosirea indexului coloanei în loc de numele său va fi mai eficientă. De asemenea, pentru maximă portabilitate se recomandă citirea coloanelor în ordine de la stânga la dreapta și fiecare citire să se facă o singură dată.
Un obiect ResultSet folosește un cursor pentru a parcurge articolele rezultate în urma unei interogări. Inițial acest cursor este poziționat înaintea primei linii, fiecare apel al metodei next determinând trecerea la următoarea linie. Deoarece next returnează false când nu mai sunt linii de adus, uzual va fi folosită o buclă while-loop petru a itera prin articolele tabelului.
Implicit, un tabel de tip ResultSet nu poate fi modificat iar cursorul asociat nu se deplasează decât înainte, linie cu linie. Așadar, putem itera prin rezultatul unei interogări o singură dată și numai de la prima la ultima linie. Este însă posibil să creăm ResultSet-uri care să permită modificarea sau deplasarea în ambele sensuri.
Dacă un ResultSet folosește un cursor modificabil și care poate naviga în ambele sensuri, atunci are la dispoziție o serie de metode ce se bazează pe acest suport:
absolute – Deplasează cursorul la o anumită linie specificată absolut;
updateXXX – Actualizează valoarea unei coloane din linia curentă, unde XXX este un tip de date.
updateRow – Transferă actualizările făcute liniei în baza de date.
moveToInsertRow – deplasează cursorul la o linie spceială, numită linie nouă, utilizateă pentru a introduce noi articole în baza de date. Linia curentă anterioară a cursorului va fi memorată pentru a se putea reveni la ea.
insertRow – inserează articolul din zona linie nou în baza de date; cursorul trebuie să fie poziționat pe linia nouă la execuția acestei operațiuni.
moveToCurrentRow – revine la linia curentă din tabel.
deleteRow – șterge linia curentă din tabel și din baza de date; nu poate fi apelată când cursorul este în modul linie nouă.
Nu toate sistemele de gestiune a bazelor de date oferă suport pentru folosirea cursoarelor care pot fi modificate. Pentru a determina dacă baza de date permite acest lucru pot fi utilizate metodele supportsPositionedUpdate și supportsPositionedDelete ale clasei DatabaseMetaData. În cazul în care acest lucru este permis, este responsabilitatea driver-ului bazei de date să asigure rezolvarea problemelor legate de actualizarea concurentă a unui cursor, astfel încât să nu apară anomalii.
CAPITOLUL 3 : PREGĂTIREA MEDIULUI DE LUCRU
NetBeans[4]
Descărcare și instalare NetBeans
NetBeans este un program Open Source și prin urmare îl putem găsi și descărca foarte ușor. Ce-a mai bună și ușoară variantă este să il descărcăm de pe site-ul Oracle unde il găsim cu tot cu driver-ul JDK ( http://www.oracle.com/technetwork/java/javase/downloads/index.html ).
Tot din cauza faptului că este un program Open Surce, NetBeans se instalează foarte ușor, neavând nevoie de activare. Tot ce trebuie să facem e să dăm dublu click pe executabilul descărcat anterior și programul aproape că se instalează singur.
Lucrul cu NetBeans
NetBeans este un mediu integrat de dezvoltare Java, care oferă foarte multe facilități. Am ales NetBeans (versiunea 7) fiindcă include și un modul de dezvoltare vizuală a interfețelor grafice, modul ce va fi utilizat ulterior. În continuare vom detalia modul de realizare a mai multor activități, folosind NetBeans:
Pentru a se crea un nou proiect, de la meniul "File -> New Project…", se selectează categoria "Java" și tipul proiectului "Java Application" (dacă s-ar fi selectat "Java Desktop Application", s-ar fi creat o aplicație vizuală, care deschide o fereastră). După ce se apasă pe "Next", va apare o fereastră în care se va specifica numele proiectului și unde anume va fi pe disc. În acest director, va fi creat un subdirector cu numele proiectului, subdirector în care se vor afla directoarele specifice diverselor componente din proiect. Dacă dorim să generam și o funcție "main", atunci se va completa numele acesteia în "Create Main Class". În fața acesteia, separat prin ".", se poate pune un nume de package pentru proiect. "Set Main Project" înseamnă că toate comenzile implicite, gen "Run", "Debug", etc…vor acționa asupra acestui proiect. După ce s-au completat aceste câmpuri ți s-a apasăt "Finish", NetBeans va crea un cadru de proiect și îl va deschide:
Central este fișierul pe care il edităm. În stânga se află managerul de proiect (Projects), de unde putem selecta orice fișier din proiect, adaugă clase noi, șterge, redenumi, schimba proprietăți de proiect, etc. Sub acesta se află navigatorul (Navigator)- o fereastră de unde putem să ajungem imediat la definitia unei clase, metode, atribut, etc. În partea de jos se află statusul curent (Tasks). Aici apar mesajele de sistem, erorile, atenționările, etc. Făcând dublu clic pe acestea, ajungem la locul lor în codul sursă. Acum apare un mesaj TODO care ne anunță că avem de implementat codul unei metode. Tot în partea de jos apare și fereastra de Output, care se activează când rulăm programul și în care se văd rezultatele execuției acestuia.
Pentru editarea codului NetBeans furnizează syntax highlighting (colorarea specifică a diverselor sectiuni/cuvinte), code autocompletion (dacă scriem un identificator și apasăm Ctrl-Space ne va apăre o lista de opțiuni de completare automată a acelui cuvânt și totodată, dacă punem un ".", ni se oferă lista de membri de unde putem alege), code navigation (cu click dreapta pe un cuvânt, "Navigate->Goto Source" (sau direct apasând pe tasta dată), putem ajunge la locul de definire a acelui cuvânt), refactorization (cu click dreapta, "Refactor->Rename") pe un cuvânt putem să-l redenumim în toate locurile în care apare în proiect, etc.
În managerul de proiect (fereastra Projects), putem (cu click dreapta) adăuga clase sau fișiere noi, modifica denumiri, șterge fișiere din proiect, muta un fișier în alt package, deschide fișiere pentru editare, schimba proprietățile proiectului, etc. Tot aici, dacă un fișier sursă conține erori, vom fi atenționați vizual printr-un mic semn de exclamare rosu, atasat acelui fișier. Pentru exemplul nostru, vom mai creea inca 2 fișiere, Shape.java si Circle.java. Crearea se face automat, cu click dreapta pe package-ul unde vrem să le cream (fis.lab4), "New->Java Class" și completând numele lor. După ce acestea vor fi create, vom face clasa Circle să extindă Shape (de exemplu, dacă după numele clasei scriem "s" și apasam Ctrl-Space – automat va apare cuvantul "extends", iar dacă după asta mai apasam odata pe Ctrl-Space, va apare o lista de clase de unde putem selecta clasa de baza).
În clasa Shape vom adăuga o noua metoda: "public abstract void draw();". După adaugarea acesteia, vom remarca în stânga numelui clasei Shape un mesaj de eroare, pe care dacă ne pozitionam cu mouseul, apare mesajul de eroare în clar. Totodată acest mesaj apare și în fereastra Tasks. În cazul nostru, din cauză că metoda draw este abstractă, și clasa Shape trebuie să fie abstractă. NetBeans poate el să corecteze această problemă și dacă apăsăm pe iconul de eroare din stânga numelui clasei, ni se prezintă sugestia de a face class Shape abstractă, sugestie pe care o vom selecta. În fereastra Tasks, pentru a se vedea noul status al unui fișier, trebuie prima oara să salvam acel fisier.
Dacă ne vom întoarce acum la clasa Circle, vom constata și aici că a aparut o eroare, pe care NetBeans o poate solutiona automat: Circle fiind derivata dintr-o clasă abstractă, trebuie să fie ori abstractă ori să implementeze toate metodele abstracte. Selectăm iconul de eroare din stânga numelui și folosim sugestia "Implement all abstract methods". Automat în class Circle va apăre implementarea metodei draw din Shape. Totodată, în clasa Circle dorim să rescriem metoda toString din Object, pentru ca atunci cand afișăm un cerc la consolă să apară un mesaj formatat inteligibil. Pentru aceasta NetBeans ne pune la dispoziție opțiunea "Insert Code", din meniul contextual care apare când facem click dreapta în editor. La "Insert Code" vom selecta metoda toString. În această situație NetBeans știe că toString are o funcție mai specială, și ne propune să selectăm ce câmpuri vom dori să le afișăm. Le lăsăm pe toate selectate, și apăsăm "Generate". În final codul pentru Circle va arăta cam asa:
Mesajul de TODO a dispărut fiindcă în Main am făcut urmatoarele modificări:
package fis.lab4;
public class Main{
public static void show (Objecto)
{System.out.println(o.toString());}
public static void main(String[] args) {
show("hi");
}
}
Dacă dorim acum să creăm un cerc și să-l afișăm, vom scrie urmatorul cod (în metoda main):
public static void main(String[] args) {
show("hi");
Circle c=null;
c.x=100;
c.y=200;
c.r=50;
show(c);
}
În NetBeans putem rula un program de la meniul "Run->Run Main Project" sau direct cu tasta F11. La rulare se deschide fereastra Output, în care apare mesajul "hi" și după el o excepție de tip null pointer. Dacă apăsăm pe link-ul asociat cu ea, ajungem la linia "c.x=100;". În cazul nostru să presupunem că nu știm de ce a aparut această eroare și dorim să rulăm programul pas cu pas, pentru a vedea ce se petrece. Pentru aceasta, vom folosi Debugger-ul integrat în NetBeans. Înainte de a porni debuggerul, vom seta un Breakpoint pe linia "c.x=100;", cu click dreapta și "Toggle Line Breakpoint". Vom vedea cum linia devine cărămizie și în dreapta ei apare un mic patrat tot cărămiziu. Dacă cumva am pus breakpointul pe alta linie, îi mai putem da odată "toggle" ca să dispară, și îl punem unde dorim. Breakpointuri se pot pune și făcând click pe bara din stânga codului. Breakpointurile reprezintă puncte în care, dacă rulăm programul în debugger, execuția se suspendă automat pentru a putea inspecta codul. Putem avea oricâte breakpointuri. După ce l-am setat, selectăm "Debug -> Debug Main Project". Vom remarca schimbarea în NetBeans când rulează debuggerul:
Cu verde apare linia care urmează să se execute. Fereastra Variables conține variabile pe care NetBeans le-a ales automat să le afișeze, dar putem să ne adăugăm și noi propriile noastre variabile. În același timp, dacă mișcăm mouseul peste un simbol (în acest caz mouseul este peste "c"), va apăre o fereastră cu valoarea acelui simbol. În bara de sus mai apar niște butoane, începând cu butonul pătrat roșu cu un alt pătrat mai mic în el. Aceste butoane au următoarele acțiuni:
Finish Debugger Session – oprește execuția programului din debugger și revine la modul obișnuit de editare
Pause – dacă se execută o rutină mai lungă, putem suspenda programul, pentru a inspecta diverse atribute ale sale
Continue – continuă programul până la următorul breakpoint sau până la terminare
Step Over – avansează execuția programului la următoarea linie, fără a se intra în subrutine, dacă pe linia curentă se afla un apel de metodă
Step Over Expression – avansează execuția programului peste o întreagă expresie, fără a se intra în constructori, funcții, etc
Step Into – dacă pe linia curentă se află un apel de metodă (sau constructor), va continua execuția intrând în acea metodă
Step Out – dacă suntem într-o metodă, execută tot codul din metodă, până când se iese din ea
În cazul nostru constatăm că eroarea a apărut din cauză că c este null, așa că vom opri debuggerul și vom înlocui linia "Circle c=null;" cu linia ""Circle c=new Circle();" (după new (și spațiu) putem apăsa pe Ctrl-Space pentru a fi ajutați să scriem mai repede codul). La următoarea rulare ("Run" sau F11), vom constata că programul rulează corect.
La fel cum în C fișierul final pentru un program este un fișier .exe (în Windows), care poate fi executat în mod direct, în Java, când vom livra programul beneficiarului, trebuie să cream un fișier .jar, care va conține toată aplicația și pe care il vom putea distribui. Pentru a se crea acest fișier, în fereastraProjects facem click dreapta pe numele proiectului (Exemplu) și selectăm opțiunea "Clean and Build". Aceasta va creea în subdirectorul "dist" din directorul aplicției un fișier "Exemplu.jar", care va conține toată aplicația. Acest fișier poate fi rulat cu dublu click, sau din linie de comanda cu "java -jar Exemplu.jar" dar, din cauză că după afișare consola dispare imediat, nu vom vedea pe ecrat niciun rezultat. Pentru a vedea un rezultat, trebuie să-l rulam de la "Command Prompt" cu comanda "java -jar Exemplu.jar" (schimbând prima oară directorul în directorul "dist"). Pentru aplicațiile grafice, se poate rula direct fișierul jar, apărând pe ecran fereastra aplicației.
Cele mai utile 10 scurtături în NetBeans
CTRL+F12 – navighează la metoda din clasa creată
Când ai foarte mult cod devine obositor să stai să cauți în clasele respective acele metode, dar treaba se ușurează cu această casuță de dialog:
SHIFT+ESC maximizează/minimizează editorul
Dacă vrei să fii concentrat mai mult în cod, îl dai fullscreen și așa știi sigur că te concentrezi 110% pe el.
CTRL+7 deschide fereastra cu navigatorul (scheletul codului)
După ce-ai dat full screen la cod, consideri că te-ai pierdut, iată că nu e așa dacă apeși CTRL+7, ai o mică hartă în față ce te-ndrumă în codare.
CTRL+/ comentează linia
Scurtătura aceasta e universală la aproape toate editoarele de cod.
ALT+SHIFT+F formatează codul
Gândiți-vă la CodeBeautifier al Sublime Textului. Aranjează codul în pagină pentru a-i reda claritate.
CTRL+0 Activează editorul (deschide fereastra editorului)
Când ești în navigator (ctrl+7) și vrei să revii în editor, folosești această combinație și ești gata de codare.
CTRL+# activează diferite ferestre
Când vrei să navighezi dintr-o parte în alta prin ferestre, poți încerca urmatoarele scurtături:
CTRL+1 – Project window
CTRL+2 – Files window
CTRL+3 – Favorite window
CTRL+4 – Output window
CTRL+5 – Services window
CTRL+6 – Tasks window
ALT+INSERT generează cod
Când vrei să generezi get-ere, set-ere sau construct-ere, combinația asta iți bagă codul direct.
ALT+F7 găsește unde mai este utilizat prin fișiere
Dacă urmărești o metodă ce nu se lasă prinsă, această scurtătură te scapă de stresul de-a căuta în toate fișierele.
CTRL+F4 închide fereastra curentă a editorului și CTRL+SHIFT+F4 închide toate ferestrele editorului
Xampp
Despe Xampp[6]
XAMPP este un pachet de programe free software, open source și cross-platform web server, care constă în Apache HTTP Server, MySQL database și interpretoare pentru scripturile scrise în limbajele de programare PHP și Perl.
Caracteristici și cerințe
Pentru a instala XAMPP, trebuie descărcat kitul de instalare în unul din formatele ZIP, TAR, 7z sau EXE, fără a fi nevoie de modificarea configurării componentelor instalate. XAMPP este actualizat cu regularitate pentru toate componentele: Apache / MySQL / PHP și Perl. El vine, deasemeni, cu alte module, cum ar fi OpenSSL și phpMyAdmin.
Instalarea XAMPP ia mult mai puțin timp decât instalarea fiecărei componente în parte. Pot exista mai multe instanțe de XAMPP pe un singur computer, și fiecare instanță poate fi copiată pe alt computer.
Utilizare
În mod oficial, designerii XAMPP au avut intenția de a îl utiliza numai ca utilitar de dezvoltare, pentru a permite designerilor și programatorilor web să își testeze munca pe calculatoarele proprii, fără a avea nevoie de acces la Internet. Pentru a face posibil acest lucru, multe caracteristici de securitate importante sunt dezactivate în mod implicit. În practică, totuși, XAMPP este uneori utilizat pentru a servi pagini web în World Wide Web. Un utilitar special este asigurat pentru a proteja prin parolă cele mai importante părți ale pachetului.
XAMPP deasemeni asigură suport pentru crearea și manipularea bazelor de date în MySQL și SQLite între utilizatori.
Odată ce XAMPP este instalat, poți trata adresa de localhost a serverului XAMPP ca pe un server la distanță, prin connectarea utilizând protocolul client FTP. Utilizarea unui program ca FileZilla are multe avantaje atunci când instalezi un [CMS[content management system]] (CMS) ca Joomla. Te poți deasemeni conecta la o gazdă locală prin FTP utilizând editorul HTML propriu.
Pentru utilizatorul FTP implicit "newuser", parola FTP implicită este "wampp".
Utilizatorul MySQL implicit este "root", iar acesta nu are o parolă MySQL implicită. Cu programul batch resetroot.bat din subdirectorul mysql al directorului unde este instalat XAMPP, puteți reseta acest utilizator încât să aibă parola vidă.
Securitate în Xampp
Xampp se instalează cu setările de securitate setate implicit la nivel minim. Pentru o siguranță mai mare, după ce instalăm Xampp este bine să să îi setăm o parolă. Aceasta se face în câțiva pași simpli.
Pasul 1
Se pornește Xampp Control Panel și se dă Start la Apache HTTP Server și MySQL database.
Pasul 2
Se accesează într-un browser de net: http://localhost/xampp/ și se dă click pe Security din meniul din partea stângă.
Pasul 3
După o să se deschidă un nou tab unde o să vedem nivelurile de securitate. Tot aici avem un link pe care o să il accesăm pentru a securiza MySQL database și directorul Xampp.
Pasul 4
Aici o să setăm parolă pentru MySQL și pentru directorul Xampp.
Acum când o să accesăm http://localhost/phpmyadmin/ o să ne ceară parola.
Capitolul 4 : Descrierea aplicației
Aplicația pe care am creat-o ține evidența facturilor, chitanțelor, bonurilor fiscale și a produselor eliberate sau înregistrate pe baza acestora.
Logare
Aplicația pornește cu o fereastră de dialog unde se face autentificarea utilizatorului.
Aici se completează numele utilizatorului, parola și drepturile (Administrator sau Utilizator). Se verifică ceea ce s-a introdus cu ceea ce este înregistrat în baza de date. Dacă se potrivesc se deschide aplicația dacă nu se potrivesc o să apară mesajul :
În funcție de drepturile pe care le are fiecare utilizator se apelează interfața specifică acelor drepturi. Diferența între cele două este că utilizatorul cu drepturi de Utilizator poate doar să iși schimbe parola pe cand utilizatorul cu drepturi de Administrator poate să caute și să vadă toate conturile de utilizatori din baza de date, poate să adauge noi conturi pentru utilizatori, poate să editeze și să șteargă orice cont de utilizator.
Toate acestea sunt realizate prin următorul cod:
String sql = "select * from user where username=? and password=? and drepturi=?";
try{
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, jTextField2.getText());
ps.setString(2, jPasswordField1.getText());
ps.setString(3, jComboBox1.getSelectedItem().toString());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
if (jComboBox1.getSelectedItem().toString() == "Administrator") {
title = jTextField2.getText();
this.dispose();
MyInterface mm = new MyInterface();
mm.show();
mm.setTitle(title);
}
if (jComboBox1.getSelectedItem().toString() == "Utilizator") {
title = jTextField2.getText();
this.dispose();
MyInterface2 mm2 = new MyInterface2();
mm2.show();
mm2.setTitle(title);
}
}
else {
JOptionPane.showMessageDialog(null, "Utilizator si/sau parola si/sau drepturi incorect/e!");
jTextField2.setText(null);
jPasswordField1.setText(null);
jComboBox1.setSelectedIndex(0);
}
}
catch (Exception e) {
}
Intrări
Pentru început trebuie selectat tipul de înregistrare și în funcție de acesta devin vizibile diferite panel-uri avem de completat diferite câmpuri.
Codul ce face acest lucru este următorul:
combo = (String) jComboBox1.getSelectedItem();
if ("".equals(combo)){
jPanel2.setVisible(false);
jPanel6.setVisible(false);
jPanel7.setVisible(false);
jPanel10.setVisible(false);
jPanel11.setVisible(false);
}
if ("Factura".equals(combo)){
jPanel2.setVisible(true);
jPanel6.setVisible(false);
jPanel7.setVisible(true);
jPanel11.setVisible(false);
}
if ("Bon Fiscal".equals(combo)){
jPanel2.setVisible(false);
jPanel6.setVisible(false);
jPanel7.setVisible(true);
jPanel11.setVisible(true);
}
if ("Chitanta".equals(combo)){
jPanel2.setVisible(false);
jPanel6.setVisible(true);
jPanel7.setVisible(true);
jPanel11.setVisible(false);
}
Factură
Bon fiscal
Chitanță
După ce completăm toate câmpurile adăugăm produsele.
Produsele vor fi adăugate inițial într-un table urmând ca ulterior să fie adăugate în baza de date.
Codul ce adaugă produsele în tabelul din interfață este:
if (!"".equals(jTextField2.getText()) & !"".equals(jTextField3.getText()) & !"".equals(jTextField4.getText()) & !"".equals(jComboBox2.getSelectedItem().toString())) {
jPanel10.setVisible(true);
model3.addRow(new Object [] {jTextField2.getText(), jTextField3.getText(), jTextField4.getText(), jComboBox2.getSelectedItem().toString()});
jTextField2.setText("");
jTextField3.setText("");
jTextField4.setText("");
jComboBox2.setSelectedItem("");
}
else {
JOptionPane.showMessageDialog(null, "Toate campurile trebuiesc completate!");
}
După ce am adăugat și produsele salvăm totul. Dacă nu am completat ceva o să ne apară un mesaj de informare și nu ne lasă să salvăm, iar dacă totul este în regulă o să ne salveze datele și o să ne și informeze cu referire la aceasta.
Stoc
În acest submeniu al aplicației se afișează stocul de produse. Căutarea se face după numele produsului sau o parte din numele acestuia, iar rezultatele sunt afișate în ordine alfabetică.
Aici se va afișa toate produsele ce au fost înregistrate in baza de date ce au numele sau o parte din el asemănător cu ceea ce vom scrie in campul Nume produs. Dacă în acest camp nu scriem nimic și dăm click pe butonul Cauta o să ne afișeze toate produsele din stoc in ordine alfabetică a numelui.
Codul prin care se face interogarea și afișarea rezultatului este următorul:
jPanel9.setVisible(true);
if (model2.getRowCount() != 0){
while(model2.getRowCount() != 0) {
model2.removeRow(0);
}
}
try{
String url = "jdbc:mysql://localhost:3306/javaapp";
Connection con = DriverManager.getConnection(url, "root", "secret381");
Statement stmt = con.createStatement();
String Query = "SELECT A.nume, CASE WHEN A.nume = B.nume then A.s1-B.s2 else A.s1 end as Stoc FROM (select nume, sum(cantitate) s1 from produse GROUP by nume) A JOIN (select nume, sum(cantitate) s2 from produse_iesiri GROUP by nume) B WHERE A.nume like '%"+jTextField17.getText()+"%'";
ResultSet rs = stmt.executeQuery(Query);
while(rs.next()){
model2.insertRow(model2.getRowCount(), new Object [] {rs.getString(1), rs.getString(2)});
}
jTextField17.setText(null);
}
catch(SQLException e) {
JOptionPane.showMessageDialog(null, e.toString());
}
Ieșiri
Aici este aproximativ ca la Intrări, structura și pași sunt aceeași doar cu mici diferențe ale câmpurilor ce trebuiesc completate și cu faptul că aici sunt trecute datele celor care cumpără.
Utilizator
Această parte diferă în funcție de drepturile pe care le are fiecare utilizator.
Administrator
În această secțiune utilizatorul cu aceste drepturi poate să vadă conturile oricărui utilizator, să le editeze, să le șteargă sau să adauge noi conturi de utilizatori.
Căutarea contului unui utilizator se poate face după oricare din cele trei atribute ale fiecărui cont (nume utilizator, parolă sau drepturi). Căutarea se face, ca și în cazul stocului, după tot numele sau doar o parte din acesta și se afișează în ordina alfabetică a numelui.
Pentru adăugarea unui nou utilizator trebuie să completăm toate câmpurile.
În cazul în care nu completăm toate câmpurile sau numele utilizatorului mai există în baza de date o să fim informați de acest lucru și nu o să ni se permită salvarea utilizatorului.
Pentru a edita contul unui utilizator trebuie mai întâi să il cautăm, după ce l-am găsit îl selectăm dând click pe el in lista care ne-a apărut. În acest moment câmpurile se completează cu datele utilizatorului. Schimbăm ce dorim și apoi dăm click pe butonul Editeaza.
În caz că nu am făcut ceva bine o să fim informați cu privire la cest lucru.
Pentru a șterge un utilizator tot ce trebuie să fcem este să îl căutăm, după ce l-am identificat să il selectăm și apoi să dăm click pe butonul Sterge.
Utilizator
Utilizatorii cu aceste drepturi în această secțiune pot doar să iși modifice parola.
Schimbare parolei se face ca în cazul genereal de schimbare a unei parole și adică prin introducerea parolei actuale, introducerea unei parole noi și reintroducerea parolei noi.
În caz de orice neregularitate vom fi anunțați.
Schimbarea parolei se face prin următorul cod:
try{
String url = "jdbc:mysql://localhost:3306/javaapp";
Connection con = DriverManager.getConnection(url, "root", "secret381");
Statement stmt = con.createStatement();
String Query = "Select password from user where username like '"+getTitle()+"'";
ResultSet rs = stmt.executeQuery(Query);
if(rs.next()) {
if (rs.getString(1).equals(jPasswordField4.getText())) {
if (jPasswordField5.getText().equals(jPasswordField6.getText())) {
if(jPasswordField4.getText().equals(jPasswordField6.getText())) {
try{
String url2 = "jdbc:mysql://localhost:3306/javaapp";
Connection con2 = DriverManager.getConnection(url2, "root", "secret381");
Statement stmt2 = con2.createStatement();
String Query2 = "UPDATE user SET password = '"+jPasswordField6.getText()+"' where username like '"+getTitle()+"'";
stmt2.executeUpdate(Query2);
JOptionPane.showMessageDialog(null, "Parola schimbata!");
jPasswordField4.setText(null);
jPasswordField5.setText(null);
jPasswordField6.setText(null);
}
catch(SQLException e) {
JOptionPane.showMessageDialog(null, e.toString());
}
}
else {
JOptionPane.showMessageDialog(null, "Noua parola trebuie sa fie diferita de cea actuala!");
jPasswordField4.setText(null);
jPasswordField5.setText(null);
jPasswordField6.setText(null);
}
}
else {
JOptionPane.showMessageDialog(null, "Noua parola trbuie introduse de doua ori la fel!");
jPasswordField5.setText(null);
jPasswordField6.setText(null);
}
}
else {
JOptionPane.showMessageDialog(null, "Parola actuala incorecta!");
jPasswordField4.setText(null);
jPasswordField5.setText(null);
jPasswordField6.setText(null);
}
}
Concluzii
Prin dezvoltarea acestei aplicații am reușit să pun în practică multe din cunoștințele dobândite în anii de facultate. Lucrarea de diplomă m-a ajutat să imi imbunătățesc aceste cunoștințe și să le aprofundez.
Această lucrare este un start pentru o aplicație foarte complexă. Din cauza lipsei de cunoștințe în domeniul contabilități este posibil ca unele probleme, cerințe să le fi abordat diferit. Aplicația dispune de unele restricții dar poate fi îmbunătățită cu altele noi. Am încercat să fac ceva cât mai general dar aceasta poate fi dezvoltată foarte mult cu noi domenii, cum ar fi:
O parte de contabilitate a salariilor unde să se genereze automat salariul în funcție de zilele lucrate, orele suplimentare, zilele de concediu și altele.
O parte de planificare a timpului de lucru (când o persoana este liberă, când lucrează și ce schimb este).
Se poate creea o parte unde să se poată scoate sau afișa diferite statistici, grafice și alte documente necesare.
Pe viitor îmi propun dezvoltare cât mai mult a acestei aplicații. O aplicație complexă, ușor de utilizat, făra erori sau posibilitatea de a le creea.
Bibliografie
[1] – Java de la 0 la expert – Ștefan Tanasă, Cristian Olaru, Ștefan Andrei
[2] – http://www.e-scoala.ro/referate/informatica_java.html – (27-06-2015)
[3] – Curs practic de Java – Cristian Frăsinaru
[4] – Programare în Java – Curs 1
[5] – https://sites.google.com/site/codrutaistin/laborator-fis-4 – (04-07-2015)
[6] – https://ro.wikipedia.org/wiki/XAMPP – (04-07-2015)
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Utilizarea Bibliotecii Swing Si a Jdbc Pentru Realizarea Interfetelor de Gestiune a Stocurilor (ID: 124716)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
