Administrativ
Laboratoare
Tema
Teste
Resurse utile
Alte resurse
Arhiva Teme
Administrativ
Laboratoare
Tema
Teste
Resurse utile
Alte resurse
Arhiva Teme
This is an old revision of the document!
În cadrul acestui laborator veți avea de ales între a folosi IntelliJ IDEA (tutorial instalare) folosind contul de mail de la facultate (tutorial activare) sau Eclipse (tutorial instalare). Primul pas este să vă familiarizați cu structura unui proiect și a unui fișier sursă Java.
Înainte de a începe orice implementare, trebuie să vă gandiți cum grupați logica întregului program pe unități. Elementele care se regăsesc în același grup trebuie să fie conectate în mod logic, pentru o ușoară implementare și înțelegere ulterioară a codului. În cazul Java, aceste grupuri logice se numesc pachete și se reflectă pe disc conform ierarhiei din cadrul proiectului. Pachetele pot conține atât alte pachete, cât și fișiere sursă.
Următorul pas este delimitarea entităților din cadrul unui grup, pe baza unor trăsături individuale. În cazul nostru, aceste entități vor fi clasele. Pentru a crea o clasă, trebuie mai întâi să creăm un fișier aparținând proiectului nostru și unui pachet (dacă este cazul și proiectul este prea simplu pentru a-l împărți în pachete). În cadrul acestui fișier definim una sau mai multe clase, conform urmatoarelor reguli:
Pentru un exemplu de creare a unui proiect, adăugare de pachete și fișiere sursă, consultați acest link pentru IntelliJ Idea si acest link pentru Eclipse.
Conform POO, orice este un obiect, însă din motive de performanță, Java suportă și tipurile de bază, care nu sunt clase. Aceste tipuri, numite tipuri primitive, corespund tipurilor de date cel mai des folosite și sunt prezentate mai jos, alături de spațiul ocupat și intervalul corespunzător de valori:
Se observă că:
unsigned
char
este pe 16 biți și întrebuințează Unicodeboolean
nu are o dimensiune fixăvoid
nu este tip in Java, este doar un cuvânt cheie pentru cazurile în care dorim să indicăm că ceea ce se returnează este nimicSegmentele de memorie inițiale, precum și parametri de rulare sunt ilustrați mai jos.
Exemplu de declarație:
int i, j; boolean k;
/* Mutat la resurse utile - in labul acesta mentionat ca exista tipul Referinta.*/
Celelalte tipuri existente sunt clase. Instanțele claselor sunt tipuri referință. Acest lucru înseamnă că în spate, mașina virtuală Java lucrează cu pointeri la obiecte și noi folosim pointeri impliciți către zone de memorie alocate pentru obiectele utilizate. Acest lucru va avea consecințe mai târziu, când vom studia transferul parametrilor în Java.
Care este diferența dintre referințe (Java) și pointeri (C) ?
Acum e de reținut faptul că în Java nu există pointeri expliciți. Această facilitate a fost considerată generatoare de erori și nu a fost implementată. Acest lucru nu limitează capacitățile platformei.
Clasele reprezintă tipuri de date definite de utilizator sau deja existente în sistem (din class library
- set de biblioteci dinamice oferite pentru a asigura portabilitatea, eliminând dependența de sistemul pe care rulează programul). O clasă poate conține:
variabile membru
(câmpuri) și proprietăți
, care definesc starea obiectului) functii membru
, ce reprezintă operații asupra stării).
Prin instanțierea unei clase se înțelege crearea unui obiect care corespunde unui șablon definit. În cazul general, acest lucru se realizează prin intermediul cuvântului cheie new
.
Biblioteca Java oferă clase wrapper (“ambalaj”) pentru fiecare tip primitiv. Avem astfel clasele Char
, Integer
, Float
etc. Un exemplu de instanțiere este următorul:
new Integer(0);
Procesul de inițializare implică: declarare, instanțiere și atribuire. Un exemplu de inițializare este următorul:
Integer myZero = new Integer(0);
Un alt exemplu de clasă predefinita este clasa String
. Ea se poate instanția astfel (nu este necesară utilizarea new
):
String s1, s2; s1 = "My first string"; s2 = "My second string";
Această este varianta preferată pentru instanțierea string-urilor. De remarcat că și varianta următoare este corectă, dar ineficientă, din motive ce vor fi explicate ulterior.
s = new String("str");
Un câmp este un obiect având tipul unei clase sau o variabilă de tip primitiv. Dacă este un obiect atunci trebuie inițializat înainte de a fi folosit (folosind cuvântul cheie new
).
class DataOnly { int i; float f; boolean b; String s; }
Declarăm un obiect de tip DataOnly
și îl inițializăm:
DataOnly d = new DataOnly(); // set the field i to the value 1 d.i = 1; // use that value System.out.println("Field i of the object d is " + d.i);
Observăm că pentru a utiliza un câmp/funcție membru dintr-o funcție care nu aparține clasei respective, folosim sintaxa:
classInstance.memberName
O proprietate este un câmp (membru) căruia i se atașează două metode ce îi pot expune sau modifica starea. Aceste doua metode se numesc getter
si setter
.
class PropertiesExample { String myString; String getMyString() { return myString; } void setMyString(String s) { myString = s; } }
Declarăm un obiect de tip PropertiesExample
și îi inițializăm membrul myString
astfel:
PropertiesExample pe = new PropertiesExample(); pe.setMyString("This is my string!"); System.out.println(pe.getMyString());
Putem modifica programul anterior astfel:
String s1, s2; s1 = "My first string"; s2 = "My second string"; System.out.println(s1.length()); System.out.println(s2.length());
Va fi afișată lungimea în caractere a șirului respectiv. Se observă că pentru a aplica o funcție a unui obiect, se folosește sintaxa:
classInstance.methodName(param1, param2, ..., paramN);
Funcțiile membru se declară asemănător cu funcțiile din C.
În limbajul Java (şi în majoritatea limbajelor de programare de tipul OOP), orice clasă, atribut sau metodă posedă un specificator de acces, al cărui rol este de a restricţiona accesul la entitatea respectivă, din perspectiva altor clase. Există specificatorii:
public
- permite acces complet din exteriorul clasei curenteprivate
- limitează accesul doar în cadrul clasei curenteprotected
- limitează accesul doar în cadrul pachetului, clasei curente si a celor care o mostenesc (conceptul de descendenţă sau de moştenire va fi explicat mai târziu)protected
!Încapsularea se referă la acumularea atributelor şi metodelor caracteristice unei anumite categorii de obiecte într-o clasă. Pe de altă parte, acest concept denotă şi ascunderea informaţiei de stare internă a unui obiect, reprezentată de atributele acestuia, alături de valorile aferente, şi asigurarea comunicării strict prin intermediul metodelor (interfata clasei).
Acest lucru conduce la izolarea modului de implementare a unei clase (atributele acesteia şi cum sunt manipulate) de utilizarea acesteia. Utilizatorii unei clase pot conta pe funcţionalitatea expusă de aceasta, indiferent de implementarea ei internă (chiar şi dacă se poate modifica în timp). Dacă utilizatorii ar avea acces la modul efectiv de implementare a unei clase, ar fi imposibilă modificarea implementării ei (necesitate care apare des în practică) fără un impact lateral asupra utilizatorului.
Clasa VeterinaryReport
este o versiune micșorată a clasei care permite unui veterinar să țină evidența animalelor tratate, pe categorii (câini/pisici):
public class VeterinaryReport { int dogs; int cats; public int getAnimalsCount() { return dogs + cats; } public void displayStatistics() { System.out.println("Total number of animals is " + getAnimalsCount()); } }
Clasa VeterinaryTest
ne permite să testăm funcționalitatea oferită de clasa anterioară.
public class VeterinaryTest { public static void main(String[] args) { VeterinaryReport vr = new VeterinaryReport(); vr.cats = 99; vr.dogs = 199; vr.displayStatistics(); System.out.println("The class method says there are " + vr.getAnimalsCount() + " animals"); } }
null
și tipurile primitive la 0 (pentru tipul boolean
la false
). VeterinaryReport.java
și VeterinaryTest.java
. Obiectele au fiecare propriul spațiu de date: fiecare câmp are o valoare separată pentru fiecare obiect creat. Codul următor arată această situație:
public class VeterinaryTest { public static void main(String[] args) { VeterinaryReport vr = new VeterinaryReport(); VeterinaryReport vr2 = new VeterinaryReport(); vr.cats = 99; vr.dogs = 199; vr2.dogs = 2; vr.displayStatistics(); vr2.displayStatistics(); System.out.println("The first class method says there are " + vr.getAnimalsCount() + " animals"); System.out.println("The second class method says there are " + vr2.getAnimalsCount() + " animals"); } }
Se observă că:
dogs
aparținând obiectului vr2
a fost actualizat la valoarea 2, câmpul dogs
al obiectului vr1
a rămas la valoarea inițiala (199). Fiecare obiect are spațiul lui pentru date!System.out.println
se întâmplă pentru orice obiect și primitivă, nu doar pentru întregi.ComplexNumber
.ComplexNumber.java
. Aceasta va avea două campuri: re
si im
, ambele de tip float
.Operations.java
. Această clasă va implementa operațiile de adunare și înmulțire pentru numere complexe. Definiți în clasă Operations
câte o metodă pentru fiecare operație; Bookstore
.Book.java
cu următoarele atribute: title
, author
, publisher
, pageCount
.BookstoreTest.java
, pentru a testa viitoarele funcționalități ale bibliotecii. Completați această clasă, așa cum considerați necesar. Apoi, creați un obiect de tip carte și setați atributele introducând date de la tastatură. Pentru această folosiți clasa Scanner
:BookstoreCheck
, ce va conține două metode, cu câte 2 parametri de tipul Book
. String
BOOK_TITLE: [insert_book_title] BOOK_AUTHOR: [insert_book_author] BOOK_PUBLISHER: [insert_book_publisher]
Cu următoarele precizări: