0% au considerat acest document util (0 voturi)
14 vizualizări787 pagini

Java

Încărcat de

madalinoprea1992
Drepturi de autor
© © All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca PPTX, PDF, TXT sau citiți online pe Scribd
0% au considerat acest document util (0 voturi)
14 vizualizări787 pagini

Java

Încărcat de

madalinoprea1992
Drepturi de autor
© © All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca PPTX, PDF, TXT sau citiți online pe Scribd

Metode. Scopul unei variabile. Recursivitate.

O clasa reprezinta un
Deoarece Java este un limbaj orientat spre
obiecte, codul este definit in interiorul unei sablon (template) al
clase.
unui obiect.

In clasa definim starea


si comportamentul
obiectului.
Metode. Scopul unei variabile. Recursivitate.

Starea este Cu alte cuvinte putem spune ca clasele sunt


alcatuite din campuri (proprietati/atribute) si
reprezentata de metode.

campuri (numite si
proprietati), iar
comportamentul este
definit cu ajutorul
metodelor.
Metode. Scopul unei variabile. Recursivitate.

De exemplu: obiectul public class Cat {


“pisica” are o stare: String color;
int hairLength;
este de culoare gri, String breed;

are parul scurt, public void makeSound(){


System.out.println("Miau");
}

rasa British Shorthair public void eat(){


System.out.println("I'm eating....");
si un comportament: }

miauna, toarce, }
//......

mananca, doarme.
Metode. Scopul unei variabile. Recursivitate.

De ce sunt importante metodele?


De ce avem nevoie de metode?
Metode. Scopul unei variabile. Recursivitate.

Un program este un
De ce sunt importante metodele?
set de obiecte care
De ce avem nevoie de metode? interactioneaza
unele cu celelalte
prin intermediul
metodelor.

Metodele contin instructiuni care sunt


executate cand metodele sunt apelate.
Metode. Scopul unei variabile. Recursivitate.

In alte limbaje intalnim concepte similare


dar denumite diferit, in unele limbaje sunt
numite functii (Javascript) sau proceduri
(Cobol, Pascal).
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Modificatorul de acces – este optional si defineste tipul de acces pe care il avem asupra
metodei. Modificatorii de access sunt public, private, default(nespecificat) sau protected.
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Static - daca o metoda este statica asta inseamna ca apartine clasei, daca nu este statica
apartine instantei/obiectului.
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Tipul returnat de metoda – este obligatoriu


O metoda poate returna un rezultat, de exemplu o metoda care calculeaza o suma returneaza
un rezultat de tip numeric (int, long, double, float).
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Rezultatul returnat de metoda poate fi de orice tip:


- primitive: int, char, boolean, double;
- clase wrapper: Integer, Boolean, Float;
- clase definite de noi sau de limbajul Java: String, MyClass, Pisica.
- void: este un tip special care este folosit atunci cand metoda nu returneaza nimic, asadar
daca avem o metoda care nu trebuie sa returneze o valoare, ci doar sa afiseze un mesaj de
exemplu, in acest caz returnType va fi cuvantul cheie “void”.
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Numele metodei – este obligatoriu


Programatorul alege numele metodei, insa trebuie sa tina seama de cateva bune practici si
reguli:
- numele metodei nu poate fi un cuvant cheie din limbajul Java, de exemplu “public”, “static”, “new”, “class”
- nu poate incepe cu numere
- trebuie sa inceapa cu litera mica si sa respecte regula de scriere camel case daca este alcatuit din mai multe cuvinte
- e de preferat sa arate o actiune, sa contina un verb, care sa arate ce anume face metoda respectiva, de exemplu: print
sau printText, calculateSum, changeName, deleteValue.
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Exemple de ASA NU: sumaADouaNumereIntregi(…), plimbareCuBicicletaPrinPadure(…), abc(…)


Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Argumentele unei metode – sunt definite in interiorul a doua paranteze rotunde

- parantezele sunt obligatorii chiar daca metoda nu asteapta nici un parametru,


deci daca avem 0 argumente tot trebuie sa punem parantezele, altfel semnatura metodei nu
este valida
Metode. Scopul unei variabile. Recursivitate.

Sintaxa unei metode:

<access modifier> <static> <return value type> <method name> (<arguments>){


<method body>
}

//Exemplu concret
public static void main(String[] args) {
// write your code here
}

Corpul metodei
- corpul metodei sta in interiorul a doua acolade obligatorii pentru metodele concrete,
- corpul metodei poate avea zero, una sau mai multe linii de cod si reprezinta logica executata
de metoda.
Recapitulare …
Metode. Scopul unei variabile. Recursivitate.

Ce este o clasa?
Metode. Scopul unei variabile. Recursivitate.

O clasa reprezinta un
Ce este o clasa?
sablon (template) al
unui obiect. Clasa este
alcatuita din campuri
(proprietati) (starea
obiectului) si metode
(comportamentul
obiectului).
Metode. Scopul unei variabile. Recursivitate.

Ce reprezinta numele metodei?


Metode. Scopul unei variabile. Recursivitate.

• este obligatoriu
Ce reprezinta numele metodei?
• trebuie sa fie cat mai descriptiv
• trebuie sa arate o actiune
• trebuie scris camelCase
• trebuie sa nu fie cuvant cheie din java
• Trebuie sa incepa cu o litera,
underscore sau $ (dollar sign)
Metode. Scopul unei variabile. Recursivitate.

Ce returneaza o metoda?
Metode. Scopul unei variabile. Recursivitate.

• tipul returnat este obligatoriu


Ce returneaza o metoda?
• cand nu returneaza o valoare atunci
tipul specificat trebuie sa fie void
• daca metoda returneaza o valoare,
atunci in interiorul ei regasim cuvantul
cheie return;
• rezultatul returnat de metoda poate fi de
orice tip: primitiv, clasa wrapper, clasa
definita de noi sau de limbajul Java
Metode. Scopul unei variabile. Recursivitate.

Cum se numeste metoda de intrare in orice


program Java?
Metode. Scopul unei variabile. Recursivitate.

Cum se numeste metoda de intrare in orice


program Java?

• main
Metode. Scopul unei variabile. Recursivitate.

Cum se numeste blocul de cod din interiorul


acoladelor unei metode?
Metode. Scopul unei variabile. Recursivitate.

Cum se numeste blocul de cod din interiorul


acoladelor unei metode?

• Corpul metodei.
Metode. Scopul unei variabile. Recursivitate.

Ce contine corpul metodei?


Metode. Scopul unei variabile. Recursivitate.

Ce contine corpul metodei?

• Logica executata de metoda. Poate


contine oricate instructiuni.
Metode. Scopul unei variabile. Recursivitate.

Care este diferenta dintre o metoda statica si


una non-statica?

• O metoda este statica apartine clasei, o


metoda non-statica apartine instantei.
Scopul. (en: scope)
Metode. Scopul unei variabile. Recursivitate.

In limbajul Java putem specifica accesibilitatea sau


scopul unei variabile, a unei metode, unui
constructor sau a unei clase cu ajutorul
modificatorilor de acces.
Metode. Scopul unei variabile. Recursivitate.

Exista 4 modificatori de acces, in ordine de la • private - putem accesa membrul doar din
cel mai restrictiv la cel mai permisiv: interiorul clasei; o metoda cu modificatorul
private nu poate fi accesata din afara clasei
• default - accesul este in cadrul pachetului.
Modificatorul de acces default este atunci cand
nu specificam nici un alt modificator de acces,
asadar nu e nevoie sa scriem cuvantul default,
este implicit default daca nu este specificat unul
din ceilalti modificatori de acces.
• protected - accesul este in cadrul pachetului si in
subclase (vom vorbi de subclase in viitor)
• public - membrul poate fi accesat de oriunde
Metode. Scopul unei variabile. Recursivitate.

Access modifier within class within package outside package outside package
by subclass only

private Yes No No No

default Yes Yes No No

protected Yes Yes Yes No

public Yes Yes Yes Yes


Metode. Scopul unei variabile. Recursivitate.

Pana acum am vazut care este scopul


variabilelor si metodelor setat cu ajutorul
modificatorilor de acces.
Avem asadar urmatoarele 3 cazuri:
In continuare avem scopul unei variabile din 1 Class level scope (scop la nivel de clasa):
perspectiva locului in care aceasta este
declarata. - Variabilele din acest scope se mai numesc si
member variables.
- Variabilele sunt declarate in interiorul clasei, dar in
afara oricarei metode.
- Pot fi accesate direct de oriunde din interiorul
clasei
Metode. Scopul unei variabile. Recursivitate.

2. Method level scope (scop la nivel de metoda) -


local variables:
- Variablele declarate la nivel de metoda au scopul la
nivelul metodei respective.
- Ele nu pot fi accesate din afara metodei in care
este declarata
Metode. Scopul unei variabile. Recursivitate.

3. Block scope (scop la nivel de bloc)


- o variabila declarata in interiorul unei perechi de
acolade dintr-o metoda, au scopul doar in interiorul
acoladelor respective
- un bloc de cod poate fi scris ca atare sau poate
apartine instructiunilor if, while, for.
- in cazul instructiunii for, variabilele declarate pe
randul instructiunii, intre paranteze rotunde, au
scopul pana la terminarea acoladei.
Metode. Scopul unei variabile. Recursivitate.

Putem spune despre scope ca:


- variabilele locale au scopul in interiorul blocului de
cod in care au fost declarate
- variabilele de instanta – sunt disponibile de la
declarare si pana cand obiectul este sters din
memorie
- variabilele de clasa (static) – sunt disponibile de la
declarare pana ce programul termina executia
Recursivitate
Metode. Scopul unei variabile. Recursivitate.

Recursivitatea. Este procesul prin care o metoda se apeleaza pe ea


insasi in mod continuu.

O astfel de metoda se numeste metoda recursiva.

Inputul la fiecare apel recursiv trebuie sa fie diferit


pentru ca la un moment dat apelul recursiv sa se
finalizeze.

Ce se intampla daca nu avem pusa o conditie de


iesire?
Metode. Scopul unei variabile. Recursivitate.

Recursivitatea.

Daca nu este pusa o conditie de iesire poate rezulta


o bucla infinita. Rezultand eroarea
StackOverflowError.

Acest lucru se intampla pentru ca memoria stack


devine insuficienta daca sunt prea multe apeluri
recursive.
Metode. Scopul unei variabile. Recursivitate.

Memoria stack tine apelurile metodelor unele peste


altele, prima este cea mai de jos si ultima este cea
Recursivitatea. pozitionata sus. Apoi le executa incepand cu cea mai
recenta spre cea mai veche.
Metode. Scopul unei variabile. Recursivitate.

In general recursivitatea foloseste mai multe resurse


decat loops si daca inputul are multe elemente
poate duce la StackOverflowError.
Recursivitatea.
Atunci cand folosim recursivitatea codul tinde sa fie
mai concis.

Recursion vs Iteration (loops)


http://www.cs.cornell.edu/info/courses/spring-98/
cs211/lecturenotes/07-recursion.pdf
Despre
Programarea
Orientata spre
Obiect
Programarea Orientata spre Obiect

Programarea orientata spre obiect (P.O.O.) este o


paradigma de programare in care programele sunt
reprezentate sub forma unor colectii de obiecte ce
comunica intre ele prin intermediul metodelor lor.
Programarea Orientata spre Obiect

Limbaje de programare care folosesc paradigma P.O.O.:


Java,
C++,
C#,
Python,
etc.
Programarea Orientata spre Obiect

O aplicatie Java poate fi definita ca o colectie de obiecte ce


comunica intre ele prin invocarea metodelor lor.
Programarea Orientata spre Obiect

Clasele si obiectele sunt doua dintre conceptele de baza in P.O.O.


Programarea Orientata spre Obiect

Ce sunt obiectele?
Programarea Orientata spre Obiect

Ce sunt obiectele? Obiectele reprezinta


entitati din lumea reala si
au stare (campuri) si
comportament (metode).
Fiecare obiect reprezinta
instanta unei clase.
Programarea Orientata spre Obiect

Exemple de obiecte
Programarea Orientata spre Obiect

Catel
Stare:
Exemple de obiecte culoare, rasa, talie
Comportament:
latra, mananca,
doarme, daDinCoada

Copac
Stare:
inaltime, tip, varsta
Comportament:
infloreste, faceFructe
Programarea Orientata spre Obiect

Ce este o clasa?
Programarea Orientata spre Obiect

Ce este o clasa?

O clasa reprezinta un
sablon (template) al unui
obiect. Obiectele sunt
create pe baza claselor.
Programarea Orientata spre Obiect

Reguli pentru definirea unei clase:


- intr-un fisier cu extensia .java pot fi definite mai multe clase, insa doar
o clasa poate fi publica;
- fisierul .java care contine clasa publica are acelasi nume ca si clasa, de
exemplu clasa publica Catel se gaseste in Catel.java ;
- blocul unei clase este definit de acolade.
Programarea Orientata spre Obiect

Cum cream un obiect?


Programarea Orientata spre Obiect

Cum cream un obiect?

Catel catel = new Catel();


Programarea Orientata spre Obiect

Obiectele se aloca pe heap.


Pentru ca un obiect sa poata fi folosit, este necesara cunoasterea adresei
lui.

System.out.println(catel); //ro.company.Catel@7c30a502
Programarea Orientata spre Obiect

Catel azorel = new Catel();

Cuvantul azorel este o referinta care indica catre o zona de memorie


initializata cu template-ul clasei Catel. Cu ajutorul referintei putem accesa
obiectul din memorie.
Pentru a putea avea acces la operatiile furnizate de catre un obiect,
trebuie sa detinem o referinta spre acel obiect.
Programarea Orientata spre Obiect

Catel azorel = new Catel();

Referintele sunt denumiri / variabile care arata unde se afla un obiect in


memorie. In Java obiectele nu pot fi accesate direct, ci doar prin referinte.
Programarea Orientata spre Obiect

Cate obiecte avem in exemplul de mai jos?


Catel azorel = new Catel();
System.out.println(azorel);
//ro.company.Catel@7c30a502

Catel max = azorel;


System.out.println(max);
//ro.company.Catel@7c30a502
Programarea Orientata spre Obiect

Avem un singur obiect ce are adresa in memorie:


ro.company.Catel@7c30a502.
Catel azorel = new Catel();
Insa avem doua referinte catre aceeasi zona de
System.out.println(azorel);
memorie: azorel si max.
//ro.company.Catel@7c30a502
Atribuirea de referinte nu creeaza o copie a
obiectului.
Catel max = azorel;
System.out.println(max);
Daca am fi creat un nou obiect folosind cuvantul
//ro.company.Catel@7c30a502
cheie new atunci atunci s-ar fi alocat un nou
spatiu in memorie.
Programarea Orientata spre Obiect

Cate obiecte avem in exemplul de mai jos?

Catel azorel = new Catel();


System.out.println(azorel);
//ro.company.Catel@7c30a502

Catel max = new Catel();


System.out.println(max);
//ro.company.Catel@49e4cb85
Programarea Orientata spre Obiect

Catel azorel = new Catel();


System.out.println(azorel);
//ro.company.Catel@7c30a502 Pentru ca acum folosim new de
doua ori, azorel refera un obiect in
Catel max = new Catel(); memorie, iar max alt obiect.
System.out.println(max); Asadar avem doua obiecte.
//ro.company.Catel@49e4cb85
Programarea Orientata spre Obiect

Am vazut pana acum ca o clasa contine:


- cuvantul cheie class,
- denumire,
- specificatori de acces
- membri (campuri si metode) cu specificatori de acces

Orice clasa contine in plus cel putin un constructor.


Programarea Orientata spre Obiect

Ce este un constructor?
Programarea Orientata spre Obiect

Ce este un constructor?

Un constructor este un bloc


de cod ce este apelat la
crearea unui nou obiect.
Programarea Orientata spre Obiect

Reguli pentru definirea unui constructor:


- constructorul are acelasi nume precum clasa in care este declarat.
- constructorul poate avea orice modificator de acces.
- constructorul nu are return type, nici macar void
Programarea Orientata spre Obiect

Exemplu de constructor fara parametri:


public class Catel {
public Catel() {
}
}
Programarea Orientata spre Obiect

Nu este obligatoriu ca programatorul sa defineasca un constructor intr-o clasa.


In cazul in care programatorul nu defineste un constructor, atunci compilatorul va
insera un constructor default, fara argumente.

Daca programatorul defineste un constructor, atunci compilatorul nu mai insereaza


constructorul default.
Programarea Orientata spre Obiect

Este de asemenea posibil ca un constructor sa primeasca si argumente, asemanator


unei metode.
Aceste argumente sunt folosite pentru a initializa starea obiectului nou creat.
Programarea Orientata spre Obiect

package ro.company;

public class Catel {


//stare
private String rasa;
private Integer varsta;

public Catel(String rasa, Integer varsta) {


this.rasa = rasa;
this.varsta = varsta;
}
}

In exemplul de mai sus, in clasa Catel am declarat un constructor care asteapta doi
parametri: rasa si varsta.
Programarea Orientata spre Obiect

Deoarece am definit constructorul respectiv, compilatorul nu va adauga automat un


constructor default (care nu asteapta parametri).

Asta inseamna ca daca incercam sa cream un obiect de tipul Catel fara sa trimitem cei
doi parametri asteptati, codul nu va compila.

Catel azorel = new Catel(); //NU COMPILEAZA

La crearea obiectului va trebuie sa apelam constructorul astfel:

Catel azorel = new Catel(“Poodle", 2);


Programarea Orientata spre Obiect

Cuvantul cheie this refera instanta curenta a clasei unde este folosit.
Poate fi folosit de metodele non-statice pentru a se referi la instanta curenta.

Exemplu:
public class Catel {
//stare
private String rasa;
private Integer varsta;

public Catel(String rasa, Integer varsta) {


this.rasa = rasa;
this.varsta = varsta;
}
}
Programarea Orientata spre Obiect

Supraincarcarea
Supraincarcarea este procedeul prin care putem avea mai multi constructori in aceeasi
clasa, dar care difera prin parametrii pe care acestia ii asteapta.
Programarea Orientata spre Obiect

public class Catel {


private String rasa;
private Integer varsta;

public Catel() {
}

public Catel(Integer varsta) {


this.varsta = varsta;
}

public Catel(String rasa, Integer varsta) {


this.rasa = rasa;
this.varsta = varsta;

//putem avea un constructor care primeste aceeasi parametri, dar ordinea acestora difera (au tip diferit)
public Catel(Integer varsta, String rasa) {
this.varsta = varsta;
this.rasa = rasa;
}
}
Programarea Orientata spre Obiect

Daca avem clasa Composer care are proprietatile name si favouriteSong, nu putem avea doi constructori cu aceeasi parametri, dar
inversati pentru ca tipul lor este acelasi (String)

public class Composer {


private String name;
private String favouriteSong;

public Composer(String name, String favouriteSong) { //nu compileaza, denumirea referintei nu conteaza ci tipul
this.name = name;
this.favouriteSong = favouriteSong;
}

public Composer(String favouriteSong, String name) { //nu compileaza


this.favouriteSong = favouriteSong;
this.name = name;
}
}
Programarea Orientata spre Obiect

Putem aplica supraincarea atat constructorilor, cat si metodelor.


Asadar intr-o clasa putem avea mai multe metode cu aceeasi denumire, dar cu
parametri diferiti.
Programarea Orientata spre Obiect

Exemple de metode supraincarcate:

class Baker {
public boolean bakeBread(String recipe) {
// do something
}

protected void bakeBread(String recipe, LocalTime time) {


// do something else
}

// chiar daca are acelasi numar de parametri cu metoda de mai sus, tipul acestora difera (difera pozitia lor)
public void bakeBread(LocalTime cookingTime, String recipe) {
// bake the bread differently
}

// daca mai adaugam inca o metoda care primeste o lista cu doua argumente,
//dar acestea au acelasi tip ca o alta metoda definita in aceeasi clasa, atunci codul nu va compila
public void bakeBread(LocalTime cookingTime, String ingredients) {
// NU COMPILEAZA
}
}
Programarea Orientata spre Obiect

Exemple de metode supraincarcate:

public class Composer {

public void writeSong() {


System.out.println("Na nana na");
}

public void writeSong(String style) {


System.out.println("Here is a " + style + " song: la lala la");
}

public void writeSong(String style, String key) {


System.out.println("I wrote a " + style + " song in " + key);
}

public static void main(String[] args) {


Composer composer = new Composer();
composer.writeSong();
composer.writeSong("rock");
composer.writeSong("pop", "C major");
}
}
Programarea Orientata spre Obiect

Memoria Java
JVM imparte spatiul de memorie in doua parti:
1. Stack
2. Heap
Programarea Orientata spre Obiect

Spatiul de stocare stack

Este o regiune din memoria computerului care stocheaza temporar variabilele create
de fiecare metoda din programul Java.
Stack este o structura de date de tipul LIFO (last in, first out).
Cand programul termina de executat o metoda, toate variabilele stocate pe stack
folosite de metoda respectiva, sunt sterse de pe stack, regiunea de memorie
respectiva eliberandu-se pentru a putea stoca o alta variabila locala.

Tot acest proces se intampla automat, programatorul nu trebuie sa se ocupe de


alocare/eliberare memorie deoarece CPU-ul organizeaza memoria stack eficient,
citirea si scrierea variabilelor facandu-se foarte rapid.
Programarea Orientata spre Obiect

Spatiul de stocare stack este limitat. Cand memoria stack este plina, Java arunca o
eroare de tipul java.lang.StackOverflowError.
In memoria Stack blocurile se stocheaza in ordinea LIFO in timp ce memoria Heap
foloseste alocare dinamica pentru a aloca si dealoca blocuri de memorie.
Programarea Orientata spre Obiect

Spatiul de stocare Heap

Este folosit pentru alocarea dinamica a memoriei pentru obiecte si clasele continute
de JRE la runtime. Obiectele sunt stocate in memoria Heap, iar referintele catre aceste
obiecte sunt stocate in memoria Stack.

Obiectele au acces global, pot fi accesate de oriunde din aplicatie.

Cand memoria heap este plina, Java arunca o eroare de tipul


java.lang.OutOfMemoryError.
Programarea Orientata spre Obiect

Pentru mai multe informatii despre cele doua : https://www.baeldung.com/java-stack-


heap
Recapitulare
OOP

La ce ne ajuta constructorii?
OOP

La ce ne ajuta constructorii?

Constructorii ne ajuta la
crearea de noi obiecte.
OOP

Unde sunt alocate obiectele nou create?


OOP

Unde sunt alocate obiectele nou create?

Pe heap.
OOP

Cum putem accesa obiectele stocate in


memoria heap?
OOP

Cum putem accesa obiectele stocate in


memoria heap?

Cu ajutorul referintelor.
OOP

Unde sunt stocate referintele?


OOP

Unde sunt stocate referintele?

Pe stack.
OOP

Cati constructori definiti de programator avem


in urmatorul exemplu:

public class Person {


private int age;
private String name;

public void Person() {


//do something
}
}
OOP

Cati constructori definiti de programator avem


in urmatorul exemplu:

public class Person {


private int age;
private String name; Zero
public void Person() {
//do something
}
}
OOP

Care sunt regulile pentru definirea unui


constructor?
OOP

Care sunt regulile pentru definirea unui


constructor?

- constructorul are acelasi nume precum clasa in care este


declarat.
- constructorul poate avea orice modificator de acces.
- constructorul nu are return type, nici macar void
OOP

Cati constructori definiti de programator sau de


catre Java avem in urmatorul exemplu:

public class Person {


private int age;
private String name;

}
OOP

Cati constructori definiti de programator sau de


catre Java avem in urmatorul exemplu:

public class Person {


private int age;
private String name; - unu, constructorul default definit de Java

}
OOP

Cati constructori definiti de programator sau de


catre Java avem in urmatorul exemplu:

public class Person {


private int age;
private String name;

public Person(int age, String name) {


this.age = age;
this.name = name;
}
}
OOP

Cati constructori definiti de programator sau de


catre Java avem in urmatorul exemplu:

public class Person {


private int age;
private String name; - unu, constructorul definit de programator care primeste
doua argumente
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
OOP

Dar in urmatorul exemplu, cati constructori


avem?

public class Person {


private int age;
private String name;

public Person() {
}

public Person(int age) {


this.age = age;
}

public void Person(String name) {


this.name = name;
}

public Person(int age, String name) {


this.age = age;
OOP

Dar in urmatorul exemplu, cati constructori


avem?

public class Person {


private int age;
private String name;

public Person() {
- trei
}

public Person(int age) {


this.age = age;
}

public void Person(String name) {


this.name = name;
}

public Person(int age, String name) {


this.age = age;
OOP

Cum se cheama procedeul prin care putem


avea mai multi constructori care primesc
argumente diferite?
OOP

Cum se cheama procedeul prin care putem


avea mai multi constructori care primesc Supraincarcare.
argumente diferite?
OOP

Constante
OOP

O constanta in Java este o variabila a carei valoare nu se


mai poate schimba o data ce a fost initializata.
OOP

Avantajele utilizarii constantelor intr-o aplicatie Java:


- codul este mai usor de citit si de inteles;
- constanta este pastrata in memorie (in cache) de JVM => performanta este imbunatatita.
OOP

Sintaxa:

static final <var_type> NAME_SOMETHING = value;


OOP

Cuvantul cheie static asociat variabilei ne arata faptul ca variabila apartine clasei, nu instantelor
clasei respective.
OOP

Cuvantul cheie final ne arata faptul ca valoarea continuta de variabila nu poate fi modificata, este
finala.
OOP

public class ConstantsExamples {


public static final int MAX_VALUE = 60;

public static void main(String[] args) {


MAX_VALUE = 70; // NU COMPILEAZA
}
}
OOP

public class ConstantsExamples {


public static final int MAX_VALUE; // NU COMPILEAZA

public static void main(String[] args) {


MAX_VALUE = 70; // NU COMPILEAZA
}
}

O variabila de clasa final trebuie sa fie initializata de la declarare.


OOP

Este suficient sa stim ca o variabila de clasa final trebuie initializata cu o valoare de cand este
declarata si aceasta valoare nu mai poate fi modificata. Spunem despre variabilele final ca sunt
constante.
OOP

La fel ca orice alta variabila, o constanta are un tip si o denumire. Exista o conventie care spune ca
denumirea constantei trebuie scrisa cu majuscule, iar daca este alcatuita din mai multe cuvinte,
atunci despartirea se face prin underscore.

Exemple:
public static final int SECONDS_PER_MINUTE = 60;
public static final String FIRST_DAY_OF_THE_WEEK = "Monday";
OOP

Enum
OOP

Tipul enum este un tip de date special ce reprezinta un set predefinit de constante.
OOP

Ca sa cream o clasa de tip enum vom folosi cuvantul cheie enum. Enum-ul contine
constante scrise cu majuscule, separate prin virgula.
public enum DaysOfWeek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
OOP

Principiile OOP
Abstractizare (Abstractization)
Polimorfism (Polymorphism)
Mostenire (Inheritance)
Incapsulare (Encapsulation)

A-PIE
OOP

Incapsularea
OOP

Incapsularea
Este procedeul prin care variabilele unei clase sunt inaccesibile altor clase, ele nu pot fi accesate direct
de catre alte clase, ele pot fi accesate doar prin intermediul metodelor clasei in care se gasesc.

Incapsularea este cunoscuta ca "ascunderea datelor" (data hiding). Ascunderea se face cu ajutorul
modificatorului de acces private.

Datorita incapsularii, accesul si modificarea starii unui obiect se poate face doar prin accesori si
mutatori. Accesorii si mutatorii sunt metode publice cunoscute ca getteri si setteri. Setterii pot contine
conditii business.
OOP

Avantajele incapsularii
1. Clasa are control asupra informatiilor ce sunt stocate in variabilele continute de aceasta.
2. Ascunderea datelor: nu cunoastem implementarea din clasa pe care o accesesam, nu cunoastem
decat ca transmitem anumite valori catre metodele setter si variabilele vor fi initializate. Prin
incapsulare atingem si o forma de abstractizare.
3. Incapsularea ne ofera flexibilitate in sensul in care putem face ca variabilele sa fie read-only sau
write-only in functie de cerinte. Daca vrem ca utilizatorul sa nu aiba decat drept de citire asupra unei
variabile, omitem metoda setter. Daca dorim ca utilizatorul sa nu aiba decat drept de scriere asupra
unei variabile, atunci omitem getterul.
4. Incapsularea sporeste reutilizarea codului si usurinta implementarii unor noi cerinte precum si
usurinta in testarea codului.
Recapitulare
OOP

Ce este o constanta?
OOP

Ce este o constanta?

O constanta este o variabila a


carei valoare nu se mai poate
schimba odata ce a fost
initializata.
OOP

Ce inseamna final?
OOP

Ce inseamna final?

Cuvantul cheie final ne arata


faptul ca valoarea continuta
de variabila nu poate fi
modificata.
OOP

O metoda poate fi final?


OOP

O metoda poate fi final?

Da. Atat metodele cat si


clasele pot fi final insa spre
deosebire de variabilele final
au alta semnificatie.
OOP

Ce este gresit in urmatoarea bucata de cod?

public class ConstantsExamples {


public static final Integer maxValue
maxValue = 100_000;
}
OOP

Ce este gresit in urmatoarea bucata de cod?

public class ConstantsExamples {


public static final Integer maxValue;
Variabila de clasa maxValue este final
maxValue = 100_000; asadar trebuie initializata de la
} declarare. In plus, deoarece este
constanta, bunele practici spun ca
trebuie scrisa cu majuscule:
MAX_VALUE.
OOP

Ce este un enum?
OOP

Ce este un enum?

Enum este un tip de date ce


reprezinta un set de
constante.
OOP

Urmatorul enum este scris corect?

public class enum Months {


JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
// ....
DECEMBER
}
OOP

Urmatorul enum este scris corect?

public class enum Months {


JANUARY,
FEBRUARY, Nu. Daca este enum, nu are ce cauta
MARCH,
APRIL,
cuvantul class.
MAY,
JUNE,
JULY,
// ....
DECEMBER
}
OOP

Ce este gresit in urmatorul enum?

public enum DaysOfWeek {


MONDAY;
TUESDAY;
WEDNESDAY;
THURSDAY;
FRIDAY;
SATURDAY;
SUNDAY;
}
OOP

Ce este gresit in urmatorul enum?

public enum DaysOfWeek {


MONDAY; Valorile din enum sunt despartite prin
TUESDAY; virgula.
WEDNESDAY;
THURSDAY;
FRIDAY; In exemplul de mai sus, ele sunt
SATURDAY; despartite prin punct si virgula => codul
SUNDAY;
} nu va compila.
OOP

Care sunt cele 4 principii OOP?


OOP

Care sunt cele 4 principii OOP?

Incapsulare, mostenire,
abstractizare si polimorfism.
OOP

Ce este incapsularea?
OOP

Ce este incapsularea?
Este procedeul de ascundere a starii unei clase
(starea este data de variabile, ascunderea se
face cu ajutorul modificatorului de acces
private), accesul si modificarea starii unui
obiect realizandu-se doar prin metodele
speciale: getter si setter.
OOP

Care este scopul metodelor getter?


OOP

Care este scopul metodelor getter?

Getterii ne ajuta sa obtinem starea unui obiect.


OOP

Care este scopul metodelor setter?


OOP

Care este scopul metodelor setter?

Setterii ne ajuta sa initializam sau sa modificam


starea unui obiect in conditiile implementate
de noi.
OOP

In clasa Employee este implementata


incapsularea?

public class Employee {


private String name;

public String getDenumire() {


return name;
}

public void setDenumire(String denumire) {


if (denumire.length() > 3) {
this.name = denumire;
} else {
// display error message
}
}
}
OOP

In clasa Employee este implementata


incapsularea?

public class Employee { Da. Insa denumirea metodelor getter si setter


private String name; nu respecta bunele practici.
Denumirile metodelor ar fi trebuit sa fie
public String getDenumire() { getName si setName, insa nici getDenumire si
return name; setDenumire nu sunt gresite. Codul compileaza
}
cu succes.
public void setDenumire(String denumire) {
if (denumire.length() > 3) {
this.name = denumire;
} else {
// display error message
}
}
}
OOP

Ce metode trebuie omise daca dorim ca


utilizatorul sa aiba doar drept de citire asupra
starii unui obiect?
OOP

Ce metode trebuie omise daca dorim ca


utilizatorul sa aiba doar drept de citire asupra
starii unui obiect?

Metodele setter.
OOP

Mostenirea
OOP

Mostenirea in Java se refera la abilitatea unei clase de a mosteni de la


o alta clasa membrii acesteia (campuri si metode).
OOP

Ideea din spatele mostenirii este ca o clasa sa poata fi construita pe


baza altei clase existente. Pe langa proprietatile mostenite, clasa poate
contine propriile ei campuri si metode.
OOP

Cuvantul cheie care indica mostenirea este extends. Cand clasa A


mosteneste clasa B, mai putem spune ca A extinde pe B.
OOP

Mostenirea reprezinta o relatie IS-A cunoscuta si sub denumirea de


relatie parinte-copil.

public class Flower {}


public class Rose extends Flower {}

Rose IS-A Flower


OOP

Clasa care mosteneste proprietatile altei clase se numeste subclasa


(clasa-copil, clasa derivata).
OOP

Clasa care este mostenita de catre o alta clasa se numeste superclasa


(clasa-parinte, clasa de baza).
OOP

O clasa poate extinde cel mult o alta clasa.


OOP

Tipuri de mostenire in limbajul Java: single, multilevel, hierarchical

class B extinde A | class B extinde A si class c extinde class C | class B si C extind A


OOP

In mostenirea singulara, subclasele mostenesc


caracteristicile unei singure superclase.
OOP

In mostenirea multilevel, clasa-copil mosteneste


clasa-parinte pe care o extinde, iar daca clasa-
parinte extinde la randul ei o alta clasa, atunci
clasa-copil va mosteni si proprietatile
respectivei clase.
OOP

In ceea ce priveste mostenirea ierarhica, o clasa deserveste ca


superclasa (clasa de baza) pentru mai multe subclase.
OOP

Principalul avantaj al mostenirii este reutilizarea codului.

Respectand astfel principiul DRY – Don’t Repeat Yourself.


OOP

In limbajul Java exista o clasa care este superclasa tuturor celorlalte clase (definite
de Java sau construite de programator). Aceasta este clasa Object.
Atunci cand o clasa nu extinde explicit o alta clasa, ea extinde implicit clasa Object.
OOP

O clasa poate avea o singura superclasa, insa o superclasa poate avea oricate subclase.

Deoarece o clasa nu poate extinde mai multe clase putem pastra o complexitate redusa.
OOP

O subclasa mosteneste toti membrii de la clasa ei parinte*.

Constructorii nu sunt membri asadar ei nu sunt mosteniti de subclasa, dar pot fi invocati din
interiorul subclasei.

*Daca o clasa are membri (campuri, metode) declarati private, acestia nu sunt accesibili din
interiorul subclasei. Retinem ca modificatorul de acces private restrictioneaza accesul din
exteriorul clasei.
OOP

Conceptul de mostenire ne ajuta sa nu duplicam cod, clasele copil avand access la membrii non-
private ai claselor parinte, ii pot folosi ca atare sau ii pot suprascrie.
De asemenea subclasele pot avea propriile campuri si metode.
OOP

Clasele definite folosind specificatorul final nu pot fi mostenite.

public final class A {


//..
}

//NU COMPILEAZA
public class B extends A {
//..
}
OOP

Suprascrierea
OOP

Suprascrierea este capacitatea unei subclase de a avea o implementare


specifica a unei metode deja existente in superclasa.
OOP

Cand o metoda din subclasa are aceeasi semnatura (nume si parametrii)


si acelasi tip returnat ca metoda din superclasa atunci spunem despre
metoda din subclasa ca suprascrie metoda din superclasa.
OOP

Pe metodele din clasa copil care suprascriu metode din clasa parinte
putem adauga adnotarea @Override.

Aceata adnotare este optionala.

Avantejele folosirii ei sunt:


- ne atentioneaza ca metoda pe care este pusa suprascrie o alta metoda
din clasa parinte (este o adnotare marker).
- suntem atentionati cand exista erori de scriere sau cand metoda ce va
fi suprascrisa nu exista in clasa parinte.

Exemplu
- shoW(){} nu suprascrie show(){};
- process(String name) nu suprascrie process(int number);
OOP

Exemplu @Override:

public class A {
void process(String name){
System.out.println("processing...");
}
}

public class B extends A {


@Override
void process(String name) {
super.process(name);
}
}
OOP

Modificatorul de acces al metodei suprascrise trebuie sa permita un acces


egal sau mai mare decat metoda care o suprascrie.

De exemplu o metoda protected in superclasa, poate fi suprascrisa de o


metoda publica in subclasa.
OOP

public class Flower {


protected int getNumberOfPetals() {
return 5;
}
}

//this is OK, even public is ok


public class Rose extends Flower {
protected int getNumberOfPetals() {
return 15;
}
}

//this is NOT OK
public class Rose extends Flower {
private int getNumberOfPetals() {
return 15;
}
}
OOP

Metodele declarate ca final in clasa parinte, nu pot fi suprascrise.


Asa cum variabilele final nu pot fi reinitializate, valoarea declarata initial
este finala, nici metodele declarate cu specificatorul final nu pot fi
suprascrise.
OOP

public class Flower {


public final int getNumberOfPetals() {
return 5;
}
}

public class Rose extends Flower {


//this is NOT OK
public int getNumberOfPetals() {
return 15;
}
}
OOP

Super
OOP

Cuvantul cheie super este similar cuvantului cheie this.


OOP

Daca this ne ajuta sa ne referim la clasa in interiorul careia


ne aflam, cu ajutorul cuvantului cheie super putem accesa
membri din clasa parinte.
OOP

Mostenirea si
constructorii in Java
OOP

In limbajul de programare Java, constructorul fara


argumente din superclasa este apelat automat in
constructorul subclasei.

Daca superclasa are un constructor ce primeste unul sau


mai multe argumente iar cel fara argumente lipseste, atunci
toate subclasele trebuie sa apeleze pe prima linie din
constructorul lor, constructorul respectiv din superclasa
folosind super.
OOP

Metodele equals() si
hashCode()
OOP

Parintele tuturor obiectelor din Java este Object.

public class Book {


// implementare...
}

este echivalent cu

public class Book extends Object {


// implementare...
}
OOP

Clasa Object contine cateva metode ce sunt mostenite de


toate celelalte clase.

Dintre aceste metode amintim:


toString(),
equals()
hashCode().
OOP

Doua obiecte sunt egale daca folosim operatorul de


comparare == doar daca au aceeasi adresa in memorie.

Folosim == doar pentru a compara primitive.

Pentru a compara obiecte folosim metoda .equals().


OOP

Implementarea default a metodei equals() din clasa Object


verifica daca doua obiecte au aceeasi adresa in memorie la
fel ca si operatorul ==.

Rezulta ca doua obiecte sunt egale folosind .equals() doar


daca au aceeasi adresa in memorie.
OOP

public class Book extends Object {

public static void main(String[] args) {


Book book1 = new Book();
Book book2 = new Book();

System.out.println(book1.equals(book1)); //true
System.out.println(book1 == book1); //true
System.out.println(book1.equals(book2)); //false
System.out.println(book1 == book2); //false
}
}
OOP

Dar daca avem urmatorul exemplu. Ce vor afisa cele doua linii in care este apelata
metode equals?

public class Book extends Object {


private String author;
private String title;

public Book(String author, String title) {


this.author = author;
this.title = title;
}

public static void main(String[] args) {


Book book1 = new Book("J. R. R. Tolkien", "The Hobbit");
Book book2 = new Book("J. R. R. Tolkien", "The Hobbit");

System.out.println(book1.equals(book1));
System.out.println(book1.equals(book2));
}
}
OOP

Desi din punctul nostru de vedere este vorba despre aceeasi carte intrucat are
acelasi autor si acelasi titlu, implementarea default a metodei equals() compara
doar adresele din memorie.

Atunci care este scopul folosirii metodei equals pentru compararea


obiectelor?
OOP

Putem suprascrie metoda equals() astfel incat sa comparam starea a doua obiecte.

Daca starea a doua obiecte ce au adrese diferite in memorie este la fel, atunci putem considera ca cele
doua obiecte sunt egale.

public boolean equals(Book book) {


if (this.author.equalsIgnoreCase(book.author) && this.title.equalsIgnoreCase(book.title)) {
return true;
}
return false;
}

Book book1 = new Book("J. R. R. Tolkien", "The Hobbit"); //true


Book book2 = new Book("J. R. R. Tolkien", "The Hobbit"); //true
OOP

Metoda hashcode() este mostenita de toate obiectele din clasa Object.


Aceasta returneaza o valoare int dupa aplicarea unui algoritm de hashing Obiectului.

Daca apelam metoda hashcode() pe un obiect a carui stare nu s-a modificat trebuie sa primim output
aceeasi valoare.

Person person = new Person();


System.out.println(person.hashCode());
OOP

Person person = new Person();


System.out.println(person.hashCode());

Implementarea default a metodei hashCode() din clasa Object nu ia in calcul in algoritmul de hashing si
starea obiectului Person. De aceea aceasta trebuie suprascrisa.

public class Person {


private String name;

@Override
public int hashCode() {
return Objects.hash(name);
}
}
OOP

Exista un contract intre metoda equals() si hashCode() de aceea atunci cand implementam metoda equals()
este bine sa implementam si metoda hashCode() in clasele noastre.

public class Person {


private String name;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Person person = (Person) o;

return Objects.equals(name, person.name);


}

@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
OOP

Contractul dintre equals() si hashCode():

Doua obiecte egale au acelasi hashCode, insa doua obiecte


cu acelasi hashCode nu sunt neaparat egale.
Recapitulare
OOP

Ce inseamna ca o clasa B mosteneste o alta


clasa A?
OOP

Ce inseamna ca o clasa B mosteneste o alta


clasa A?

Clasa B mosteneste campurile si metodele


clasei A. Prin mostenire clasa B isi insuseste
membrii clasei A.
OOP

Care este cuvantul cheie care indica


mostenirea?
OOP

Care este cuvantul cheie care indica


mostenirea?

Extends
OOP

Ce tip de relatie indica mostenirea?


OOP

Ce tip de relatie indica mostenirea?

E relatie de tipul IS-A sau parinte-copil.


OOP

Cum se mai numesc superclasele?


OOP

Cum se mai numesc superclasele?

Clase parinte sau clase de baza.


OOP

Cum se mai numesc subclasele?


OOP

Cum se mai numesc subclasele?

Clase copil sau derivate.


OOP

Cate clase poate extinde o clasa?


OOP

Cate clase poate extinde o clasa?

Una.
OOP

Cum se numeste mostenirea in care o clasa


mosteneste indirect membrii superclasei
superclasei sale?
OOP

Cum se numeste mostenirea in care o clasa


mosteneste indirect membrii superclasei
superclasei sale?

Mostenire multilevel.
OOP

Cate subclase poate avea o clasa-parinte?


OOP

Cate subclase poate avea o clasa-parinte?

Oricate.
OOP

Cum se numeste parintele tuturor claselor din


Java?
OOP

Cum se numeste parintele tuturor claselor din


Java?

Object.
OOP

Ce este suprascrierea?
OOP

Ce este suprascrierea?

Suprascrierea este capacitatea unei subclase


de a avea o implementare specifica a unei
metode deja existente in superclasa.
OOP

Care sunt conditiile minime pe care trebuie sa


le respecte o metoda ca sa se considere ca
suprascrie o metoda din clasa parinte?
OOP

Care sunt conditiile minime pe care trebuie sa


le respecte o metoda ca sa se considere ca
suprascrie o metoda din clasa parinte?
Metoda care suprascrie trebuie sa aiba aceeasi
semnatura, acelasi tip returnat, iar
modificatorul de acces al metodei suprascrise
trebuie sa permita un acces egal sau mai mare
decat metoda care o suprascrie.
OOP

La ce ne ajuta cuvantul cheie super?


OOP

La ce ne ajuta cuvantul cheie super?

Cuvantul cheie super ne ajuta sa accesam


membri din clasa parinte.
OOP

Ce face implementarea default a metodei


equals()?
OOP

Ce face implementarea default a metodei


equals()?

Equals() verifica daca doua obiecte au aceeasi


adresa in memorie.
OOP

Ce va afisa urmatoarea bucata de cod?

String str1 = "Hello";


String str2 = new String("Hello");
String str3 = "Hello";

System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
System.out.println(str1 == str3);
System.out.println(str1.equals(str3));
OOP

Ce va afisa urmatoarea bucata de cod?


String str1 = "Hello";
String str1 = "Hello"; String str2 = new String("Hello");
String str2 = new String("Hello"); String str3 = "Hello";
String str3 = "Hello";
System.out.println(str1 == str2); //false
System.out.println(str1 == str2); System.out.println(str1.equals(str2)); //true
System.out.println(str1.equals(str2)); System.out.println(str1 == str3); //true
System.out.println(str1.equals(str3)); //true
System.out.println(str1 == str3);
System.out.println(str1.equals(str3));
OOP

Ce va afisa urmatoarea bucata de cod?

public class Person {


private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

public class Main {


public static void main(String[] args) {
Person p1 = new Person();
p1.setName("John");

Person p2 = new Person();


p1.setName("John");

System.out.println(p1 == p2);
OOP

Ce va afisa urmatoarea bucata de cod?

public class Person {


private String name;
public String getName() {
return name; Prima oara va afisa false pentru ca obiectele nu se compara
} cu ==, p1 si p2 nu au aceeasi adresa in memorie.
public void setName(String name) {
A doua oara va afisa tot false, chiar daca folosim metoda
this.name = name;
equals() pentru ca in clasa Person nu avem suprascrisa
} metoda equals(). In acest caz equals() verifica tot daca
} obiectele au aceeasi adresa in memorie. Nu tine cont de
starea/propretatile obiectelor.
public class Main {

public static void main(String[] args) {


Person p1 = new Person();
p1.setName("John");

Person p2 = new Person();


p1.setName("John");
OOP

Abstractizarea
OOP

Abstractizarea consta in ascunderea implementarii in spatele unei interfete.

Un obiect poate executa actiuni, poate comunica cu alte obiecte, isi poate schimba
starea fara a dezvalui cum au fost implementate aceste facilitati.
OOP

De exemplu daca avem un CreditCardValidator cu metoda boolean


validateCreditCard(int numarCard); noi putem folosi metoda validateCreditCard(...)
fara a stii neaparat care este implementarea.

Ne intereseaza doar ca daca apelam metoda si ii trimitem un numar de card vom


primi un raspuns, true daca cardul este valid si false daca este invalid.
OOP

Abstractizarea in Java este realizata folosind interfete si clase abstracte.


OOP

Clasele abstracte
OOP

O clasa abstracta este o clasa declarata folosind specificatorul abstract.

Poate avea metode abstracte si/sau concrete.

Daca o clasa contine cel putin o metoda abstracta, clasa respectiva trebuie sa
fie declarata abstracta, cuvantul abstract devine obligatoriu.

Sintaxa:
public abstract class Animal {
}
OOP

O metoda abstracta este o metoda care nu are implementare, dupa semnatura


metodei urmeaza punct si virgula in loc de acolada, ea poate fi declarata intr-o
clasa abstracta (cuvantul abstract este obligatoriu) sau intr-o interfata
(cuvantul abstract este implicit adaugat de compilator).

public abstract boolean hasFur();


OOP

Exemplu de clasa abstracta:

public abstract class Restaurant {


//abstract method
abstract String serveMeal();

//concrete method
void collectIngredients() {
String[] ingredients = {"flour", "sugar", "eggs", "butter"};
// do something with the ingredients
}
}
OOP

O clasa abstracta nu poate fi instantiata adica nu putem crea noi instante ale
clase folosind cuvantul cheie new.

Restaurant restaurant = new Restaurant(); //DOES NOT COMPILE


OOP

In schimb ea poate fi extinsa (extends) si deserveste ca baza pentru clasele


care o extind. Clasa abstracta devine folositoare cand este extinsa de o clasa
concreta.
O clasa concreta este prima subclasa non-abstracta care extinde clasa
abstracta. Clasa concreta este obligata sa implementeze toate metodele
abstracte mostenite.

public class ItalianRestaurant extends Restaurant {


String serveMeal() {
// return some cooked meal
}
}
OOP

Clasele concrete care extind clase abstracte trebuie sa ofere o implementare


pentru toate metodele abstracte mostenite.
OOP

Chiar daca o clasa abstracta nu poate fi instantiata direct, ea poate fi


instantiata prin clasele care o extind.

Restaurant restaurant = new ItalianRestaurant();


OOP

Folosim clase abstracte atunci cand vrem sa construim o baza pentru unul sau
mai multe obiecte a caror relatie cu clasa abstracta este IS-A.
OOP

Cuvantul cheie abstract poate fi aplicat claselor


si metodelor, dar nu si variabilelor.
OOP

O clasa abstracta nu poate fi final. Prin definitie, o clasa final este o clasa ce nu poate fi
mostenite. Insa scopul claselor abstracte este ca ele sa poata fi extinse.
OOP

O metoda abstracta nu poate fi final.


Metodele final sunt metode care nu pot fi suprascrise.
O metoda abstracta este o metoda ce nu are implementare si care trebuie sa fie
implementata (suprascrisa) in subclase.

Totodata o metoda abstracta nu poate fi privata din acelasi motiv.


OOP

Clasele abstracte pot avea membri definiti ca private, protected, default sau public, insa metodele
abstracte au modificatorul de acces public in mod implicit.

private abstract boolean hasFur(); // Nu compileaza, nu putem avea si private si abstract


abstract boolean hasFur(); //Compileaza, este public este adaugat de compilator
Recapitulare
OOP

Ce este abstractizarea?
OOP

Ce este abstractizarea?

Abstractizarea este un principiu OOP care consta in


ascunderea implementarii in spatele unei interfete.
OOP

Ce cuvant ne indica daca o clasa este abstracta


sau nu?
OOP

Ce cuvant ne indica daca o clasa este abstracta


sau nu?

Cuvantul cheie abstract.


OOP

Este obligatoriu ca o clasa abstracta sa aiba


metode abstracte?
OOP

Este obligatoriu ca o clasa abstracta sa aiba


metode abstracte?

Nu este obligatoriu ca o clasa abstracta sa aiba metode


abstracte. O clasa poate exista fara sa aiba nici o metoda,
doar ca ea nu ne ajuta la nimic.
OOP

O clasa abstracta poate contine metode


concrete?
OOP

O clasa abstracta poate contine metode


concrete?

Da, o clasa abstracta poate contine atat metode abstracte,


cat si concrete.
OOP

Ce este o metoda concreta?


OOP

Ce este o metoda concreta?

O metoda concreta este o metoda ce are un corp aflat intre


doua acolade. Corpul poate contine zero, una sau mai
multe instructiuni. O metoda ce nu are acolade, ci
declararea ei se termina in punct si virgula este o metoda
abstracta si se marcheaza cu specificatorul abstract.
OOP

Am spus ca o clasa abstracta poate contine atat


metode abstracte, cat si metode concrete.

O clasa non-abstracta poate contine metode


abstracte?
OOP

Am spus ca o clasa abstracta poate contine atat


metode abstracte, cat si metode concrete.

O clasa non-abstracta poate contine metode


abstracte? Nu.
OOP

Ce afiseaza urmatoarea bucata de cod?

public abstract class Printer {


public void printText(String text) {
System.out.println(text);
}
}

public class Main {


public static void main(String[] args) {
Printer printer = new Printer();
printer.printText("Hello!");
}
}
OOP

Ce afiseaza urmatoarea bucata de cod?

public abstract class Printer {


public void printText(String text) {
System.out.println(text);
} Codul nu compileaza deoarece Printer este o clasa
} abstracta, iar clasele abstracte nu pot fi instantiate (nu
putem avea new Printer()).

public class Main {


public static void main(String[] args) {
Printer printer = new Printer();
printer.printText("Hello!");
}
}
OOP

Cum am fi putut folosi clasa printer?


OOP

Cum am fi putut folosi clasa printer?

Cu ajutorul unei clase concrete care sa extinda clasa


Printer.
OOP

Ce tip de relatie au o clasa concreta ce extinde


o clasa abstracta?
OOP

Ce tip de relatie au o clasa concreta ce extinde


o clasa abstracta?

IS-A.
OOP

Exemplu de relatie IS-A cu obiectele din jur

Rose IS-A Flower


Chihuahua IS-A Dog
Romanian IS-A Language
OOP

Incapsulare vs. Abstractizare


OOP

Incapsularea reprezinta ascunderea informatiei (data hiding), pe cand


abstractizarea este ascunderea implementarii (detail hiding).
OOP

Folosim o clasa abstracta atunci cand vrem:


- ca respectiva clasa sa nu poata fi instantiata
- sa manipulam un set de clase printr-o interfata comuna
- sa reutilizam o serie de metode si campuri din aceasta clasa in clasele derivate.
OOP

Reguli pentru definirea si folosirea claselor abstracte:


1.) Clasele abstracte nu pot fi instantiate direct (folosind cuvantul cheie new).
2.) Clasele abstracte pot contine orice numar de metode abstracte si nonabstracte.
3.) Clasele abstracte nu pot fi final sau private.
4.) O clasa abstracta care extinde o alta clasa abstracta mosteneste toate metodele
abstracte din clasa mostenita.
5.) Prima clasa concreta care extinde o clasa abstracta trebuie sa implementeze toate
metodele abstracte.
OOP

Reguli pentru definirea metodelor abstracte:


1.) Metodele abstracte pot fi definite doar in clase abstracte.
2.) Metodele abstracte nu pot fi declarate final sau private.
3.) O metoda abstracta nu poate avea implementare in clasa abstracta in care se afla.
4.) Implementarea unei metode abstracte in subclasa se face urmarind aceleasi reguli ca
suprascrierea unei metode.
OOP

Reguli pentru suprascrierea unei metode:


- metoda din subclasa trebuie sa aiba aceeasi semnatura ca metoda din superclasa
- metoda din subclasa trebuie sa returneze acelasi tip ca metoda din superclasa (sau tip
covariant)
- modificatorul de acces al metodei din subclasa trebuie sa permita acces egal sau mai mare
decat metoda din superclasa
OOP

Tip de date covariant

In limbajul Java este obligatoriu sa specificam tipul de date returnat de o metoda.


Daca metoda nu returneaza o valoare, atunci cuvantul cheie folosit este void.
O metoda poate returna valori primitive: char, short, boolean, int, double, etc.
De asemenea poate returna tipuri de date referinta. Tipurile de date referinta sunt clase din
Java sau clase scrise de programator: String, Integer, Boolean, etc.
OOP

Cand spunem ca o metoda care suprascrie o metoda din clasa de baza trebuie sa returneze un
tip de date covariant, ne referim la faptul ca tipul de date trebuie sa fie subclasa pentru tipul
de date returnat de metoda suprascrisa.

Deci in suprascriere tipul de date returnat nu trebuie sa fie neaparat acelasi ci poate fi si de tip
copil al tipului de date suprascris.
OOP

Interfete
OOP

O interfata este un tip de date abstract ce defineste o lista de metode publice abstracte pe
care orice clasa care implementeaza interfata este obligata sa le implementeze.
O interfata este o colectie de metode abstracte. Pe langa metode abstracte, o interfata poate
contine constante, metode default si metode statice.
OOP

O interfata este similara unei clase abstracte, insa o clasa abstracta contine si implementarea
comportamentului pe cand o interfata doar defineste comportamentul.
OOP

Relatia dintre o interfata si clasa care o implementeaza este IS. (Truck is Loadable)
OOP

Interfata indica un comportament al clasei care o implementeaza.


Putem sa avem si clase si interfete denumite astfel:
Dog IS CanWalk
Bird IS CanSing
Unde IS se inlocuieste cu implements.

Sau mai putem avea:


Bicycle IS Vehicle
Circle IS GeometricFigure

De asemenea este comun ca in aplicatiile cu un anumit tip de arhitectura sa avem interfete cu denumiri ca:
PersonService
VehicleInformationService
RemoteControlService

Si clase concrete care implementeaza interfetele de mai sus si au denumirea:


PersonServiceImplementation
VehiculeInformationServiceImpl
RemoteControlServiceImpl
OOP

Interfata este folosita pentru a descrie un contract intre clase: o clasa care implementeaza o
interfata va implementa metodele definite in interfata.
OOP

Spre deosbire de clasele abstracte care sunt extinse folosind specificatorul extends, interfetele
sunt implementate folosind specificatorul implements.
OOP

//modificatorul de acces poate fi public sau nespecificat


//cuvantul cheie abstract este asumat (putem sa-l omitem, il va pune compilatorul)
//cuvantul cheie interface (obligatoriu, este in locul cuvantului cheie class)
//Runnable este denumirea interfetei

public abstract interface Runnable {

//in interfete putem defini constante


//public static final sunt cuvinte cheie asumate
public static final int MAX_KM = 10;
int MIN_KM = 1;

//public abstract = cuvinte cheie asumate, le putem omite


public abstract int getMaxKm();
}
OOP

Implementarea unei interfete

//deoarece clasa concreta Dog implementeaza interfata Runnable, trebuie sa implementam


metoda getMaxKm

public class Dog implements Runnable {


@Override
public int getMaxKm() {
return 0;
}
}
OOP

Reguli pentru definirea interfetelor


1.) Interfetele, la fel ca si clasele abstracte, nu pot fi instantiate direct.
2.) O interfata poate avea zero sau mai multe metode.
3.) O interfata nu poate fi avea specificatorul final, modificatorii de acces private
sau protected.
4.) Toate metodele non-default dintr-o interfata au modificatorii public abstract
adaugati automat de compilator.
OOP

Metode default

O metoda default este o metoda definita intr-o interfata ce are cuvantul cheie
default asociat. Pentru metodele default trebuie sa furnizam o implementare in
interiorul interfetei.
Metodele default au fost adaugate in Java 8. Necesitatea metodelor default a
aparut pentru a asigura backward compatibility pentru interfetele vechi.

public default double getTemperature() {


return 36.5;
}
OOP

Clasele concrete pot suprascrie metodele default, dar nu sunt obligate sa faca
asta cum este in cazul metodelor abstracte.
Metodele default trebuie sa fie publice, daca vor fi marcate ca private sau
protected codul nu va compila.

//NU COMPILEAZA
protected default double getTemperature() {
return 36.5;
}
OOP

Daca programatorul nu specifica nici un modificator de acces pentru o metoda


default, compilatorul oricum pune automat modificatorul public.

//public este asumat, il putem omite


default double getTemperature() {
return 36.5;
}
OOP

Nu putem avea metode default in clase concrete sau in clase abstracte.

public abstract class Animal {


public abstract boolean hasFur();

//NU COMPILEAZA
public default double getTemperature() {
return 36.5;
}
}
OOP

De asemenea, interfetele pot contine si metode statice similare metodelor


statice din clase. Metodele statice definite in interfete nu sunt mostenite de
clasele concrete ce implementeaza interfetele respective.
Metodele statice definite in interfete trebuie sa fie publice.

public static int getMinKm() {


return 0;
}
OOP

Pentru a referi o metoda statica dintr-o interfata, trebuie sa folosim numele interfetei.

De exemplu:
public interface Runnable {
//metoda statica
public static int getMinKm() {
return 0;
}
}

public class Dog implements Runnable {


public int getMaxKm() {
return Runnable.getMinKm(); //asa referim metoda statica din interfata
}
}
OOP

Am vazut in exemplul anterior ca intr-o interfata putem avea variabile.

//in interfete putem defini constante


//public static final sunt cuvinte cheie asumate (puse de compilator) deci le putem omite
public static final int MAX_KM = 10;
int MIN_KM = 1;
OOP

1.) Variabilele dintr-o interfata sunt public static final. Acesti trei specificatori sunt asumati, daca
nu sunt pusi de programator, atunci vor fi pusi automat de compilator.
Nu putem avea intr-o interfata variabile private sau protected.

//NU COMPILEAZA
private static final int MAX_KM = 10;

2.) Avand in vedere ca variabilele dintr-o interfata sunt final, atunci este obligatoriu sa le
initializam cu o valoare de la declarare.

//NU COMPILEAZA
public static final int MAX_KM;
OOP

Clase abstracte

vs
Interfete
OOP

Folosim o clasa abstracta atunci cand:

- relatia dintre clasa abstracta si clasa concreta este IS-A, (Dog is an Animal)
- reutilizam o serie metode si campuri din aceasta clasa in clasele derivate.
- avem acelasi comportament dar si aceeasi implementare a unui comportament in mai multe
clase
OOP

Folosim o interfata atunci cand:

- vrem sa avem doar o descriere a structurii, fara implementari


- avem doar acelasi compotament in mai multe clase dar nu si aceeasi implementare a lui
- relatia dintre interfata si clasa care o implementeaza este IS (Car is Movable)
OOP

Compozitia
OOP

Compozitia este conceptul prin care putem implementa o relatie de HAS-A intre doua clase.
OOP

Asemenea mostenirii, folosim compozitia pentru a reutiliza cod si


pentru a avea un design software cat mai simplu.
OOP

In Java compozitia este realizata prin declararea unor


obiecte ca variabile de instanta, campuri.
OOP

Asocierea poate fi de 4 feluri:


1. one-to-one: Country – President
2. one-to-many: Country – City
3. many-to-one: City – Country
4. many – to – many: Country – Currency (euro)
OOP

Exemplu:

public class Job { ... }

public class Person {

//compozitie,
private Job job;

}
OOP

Polimorfism
OOP

Polimorfismul este unul din conceptele esentiale din programarea orietata pe


obiect si reprezinta capacitatea obiectelor de a lua mai multe forme.
OOP

Orice obiect care trece testul IS-A mai mult de o data este considerat polimorfic.
Astfel putem spune ca toate obiectele Java sunt polimorfice deoarece trec testul
IS-A cu propriul tip, dar si cu clasa Object (clasa parinte a tuturor claselor din
Java).
OOP

Polimorfismul ne ajuta sa executam o singura actiune in moduri diferite, cu alte


cuvinte putem defini o interfata care sa aiba mai multe implementari.
OOP

Cea mai comuna utilizare de polimorfism este atunci cand folosim o referinta cu
tipul clasei parinte pentru a ne referi la un obiect al clasei copil.
Am mai vazut exemple de polimorfism si in lectiile anterioare, cand am discutat
despre abstractizare de exemplu:

Restaurant restaurant = new ItalianRestaurant();


OOP

Obiectul “restaurant” este instantiat cu o referinta catre clasa ItalianRestaurant,


insa deoarece el are tipul de date Restaurant are acces doar la metodele din clasa
Restaurant.
OOP

Putem accesa un obiect prin intermediul unei referinte. Referinta poate avea un
singur tip de date. Odata declarat, acest tip nu mai poate fi schimbat.
Tipul referintei determina metodele pe care le putem apela.
OOP

Exista doua tipuri de polimorfism:


1. Polimorfismul compile-time (polimorfism parametric sau polimorfism static) – obtinut prin
supraincarcarea metodelor.
2. Polimorfismul runtime (polimorfism de mostenire) – obtinut prin suprascrierea metodelor.
OOP

Polimorfismul compile-time este obtinut prin mecanismul de supraincarcare a unei metode. Selectia
metodei apelate se realizeaza la compilare (early binding).

Supraincarcarea este procedeul prin care putem avea mai multe metode cu acelasi nume in aceeasi
clasa, dar cu semnaturi diferite.
Semnatura poate sa difere in trei moduri:
- numarul de parametri;
- tipul de date al parametrilor;
- ordinea in care apar acesti parametri.
OOP

public class Composer {

public void writeSong() {


System.out.println("Na nana na");
}

public void writeSong(String style) {


System.out.println("Here is a " + style + " song: la lala la");
}

public void writeSong(String style, String key) {


System.out.println("I wrote a " + style + " song in " + key);
}

public static void main(String[] args) {


Composer composer = new Composer();
composer.writeSong();
composer.writeSong("rock");
composer.writeSong("pop", "C major");
}
}

Rezultat:
Na nana na
Here is a rock song: la lala la
I wrote a pop song in C major
OOP

Polimorfismul la runtime este obtinut prin mecanismul de suprascriere a unei metode. Selectia
metodei se realizeaza la rulare (late binding, runtime binding, dynamic binding).
OOP

//superclass Atunci cand declaram un obiect in acest fel, avem acces doar la
public class Book {
public void printInfo() { metodele din superclasa, nu si la cele din subclasa. Insa, deoarece
}
System.out.println("Just a book.");
metoda printInfo() este suprascrisa in subclasa, la runtime va fi
} folosita implementarea din subclasa.
//subclass of Book
public class ScienceFictionBook extends Book {
@Override
Ce rezultat va fi afisat daca rulam metoda main:
public void printInfo() { “Just a book.” sau “S.F. Book”?
System.out.println("S.F. Book");
}

public void printAdditionalInfo() {


System.out.println("The best S.F. Book");
}
}

public class Main {


public static void main(String[] args) {
//cand declaram un obiect in felul acesta, vom avea acces doar la metodele din clasa de baza
Book sfBook = new ScienceFictionBook();
//avem acces doar la metoda disponibile in clasa Book, adica la printInfo()
sfBook.printInfo();
}
OOP

Recapitularea regulilor de suprascriere a unei metode


- cele doua metode (cea originala si cea suprascrisa) trebuie sa aiba aceeasi lista de parametri;
- metoda suprascrisa trebuie sa returneze acelasi tip de date cu cel al metodei originale sau un
subtip al acestuia (tip de date covariant);
- modificatorul de acces la metodei suprascrise nu poate fi mai restrictiv decat cel al metodei
originale;
- metodele declarate final nu pot fi suprascrise;
- daca metoda nu este vizibila in clasa copil (este private), atunci nu poate fi suprascrisa. Putem avea
in clasa copil o metoda cu aceeasi semnatura si return type, doar ca nu se considera suprascriere.
OOP

Casting
OOP

Type Casting

In limbajul Java, variabilele pot fi de doua tipuri:


- primitive: byte, short, char, int, long, float, double si boolean.
- referinte

Cele 8 tipuri de date primitive au un anumit numar de biti la declarare dupa cum urmeaza:
byte - 8 bits
short - 16 bits
char - 16 bits
int - 32 bits
float - 32 biti
long - 64 biti
double - 64 biti
boolean - nu este numeric, poate lua valorile true sau false
OOP

Atunci cand vrem sa convertim o primitiva mai mica la o primitiva mai mare, nu trebuie sa facem
nimic special. Java se ocupa de convertirea valorii automat.

//de la int pe 32 de biti la long pe 64 de biti


int x = 1;
long y = x;

float a = 1.2f;
double b = a;

Aceasta conversie poate fi facuta automat deoarece atunci cand trecem de la un tip de date mai mic
la unul mai mare nu exista riscul sa pierdem informatie.
OOP

Nu acelasi lucru se poate spune despre conversia de la un tip de date mai mare la unul mai mic.
int x = 1;
long y = x;

int z = y; // NU COMPILEAZA

//trebuie sa facem cast ca sa mearga


int z = (int) y;
OOP

In exemplul anterior am vazut ca initial variabila de tip long y este initializata cu valoarea variabilei
de tip int x (valoarea 1). Atunci cand vrem sa initializam variabila de tip int z cu valoarea lui y,
compilatorul ne atentioneaza si este necesar ca intai sa ii facem cast la tipul int variabilei y.

float a = 1.2f;
double b = a; //COMPILEAZA pentru ca double este un tip de date mai mare decat float
float c = b; // NU COMPILEAZA
float c = (float) b;
OOP

Conversia de tip boxing/unboxing

In Java fiecare primitiva are o clasa wrapper asociata: Byte, Short, Character, Integer, Long, Float,
Double si Boolean.
Conversia de la primitiva la clasa wrapper si invers se face prin doua procedee numite boxing si
unboxing si este realizata de catre Java.

int a1 = 123;
Integer a2 = a1;
int a3 = a2;
OOP

Variabilele ce au tipul o clasa Wrapper pot fi convertite la tipul String cu ajutorul metodei toString().
Toate clasele Wrapper suprascriu metoda toString() din clasa Object.

Integer integer = 10;


String string = integer.toString();
OOP

Un String poate fi asignat unei variabile de tip Integer (sau de oricare alt tip clasa Wrapper) cu
ajutorul metodei valueOf().
De asemenea, un String poate fi asignat unei primitive cu ajutorul metodelor de tip parse. De
exemplu clasa wrapper Integer are o metoda statica parseInt care primeste ca parametru un String
si returneaza o variabila de tip int.

Integer integer2 = Integer.valueOf(string);


int i = Integer.parseInt(string);
OOP

Acelasi lucru este valabil si pentru alte clase Wrapper si primitiva asociata, singura exceptie de la
aceasta regula fiind Character.

Double d1 = Double.valueOf("12.5");
double d2 = Double.parseDouble("13.4");

Boolean b1 = Boolean.valueOf("true");
boolean b2 = Boolean.parseBoolean("false");
OOP

Numeric promotion

Pentru a executa o operatie aritmetica (adunare, scadere, etc.) este necesar ca ambii operanzi sa fie
compatibili din punct de vedere al numarului de biti alocati.
OOP

Java aplica urmatoarele reguli:


1. daca unul dintre operanzi este double, celalalt operand va fi promovat la tipul
double
2. altfel, daca unul din operanzi este float, atunci si celalalt operand va fi promovat la
tipul float
3. altfel, daca unul din operanzi este long, atunci si celalalt operand va fi promovat la
tipul long
4. altfel, ambii operanzi sunt considerati de tipul int
OOP

Exemplul 1:

//primul operand este de tip int


int o1 = 10;
//al doilea operand este de tipul long
long o2 = 20;
//rezultatul adunarii celor doi operanzi va avea tipul long
long result = o1 + o2;
//daca incercam sa stocam rezultatul adunarii intr-o variabila de tip int, nu va compila
int result2 = o1 + o2;
//insa daca facem cast astfel, vom putea stoca rezultatul intr-o variabila de tip int
int result3 = (int) (o1 + o2);
//sau putem face cast la int doar pentru operandul de tip long, astfel ca rezultatul dintre doi
operanzi de tip int va avea tot tipul int
int result4 = o1 + (int) o2;
OOP

Exemplul 2:

short s1 = 5;
short s2 = 3;
//rezultatul operatiei dintre doi operanzi cu tip mai mic decat int va fi convertit automat la int
int result5 = s1 - s2;
//daca incercam sa stocam rezultatul intr-o variabila de tip short, codul nu va compila
short result6 = s1 - s2;
//daca vrem ca rezultatul sa aiba tipul short, este necesar sa facem cast
short result7 = (short) (s1 - s2);
//castul trebuie facut la rezultatul operatiei, daca facem cast la fiecare operand in parte, codul tot nu
va compila
short result8 = (short) s1 - (short) s2;
OOP

Cum procedam pentru a stoca o valoare de tip double intr-o variabila de tipul int?
Codul de mai jos compileaza?

double d1 = 10;
int i1 = d1;
OOP

Nu compileaza. Trebuie sa facem cast variabilei de tip double la int.

double d1 = 10;
int i1 = (int) d1;
OOP

Dar daca vrem sa stocam valoarea lui i1 la loc intr-o variabila de tip double, sa zicem d2.
Codul va compila de data aceasta?

double d1 = 10;
int i1 = (int) d1;
double d2 = i1;
OOP

Da, va compila. Java poate face automat conversia la un tip mai mare. Insa atunci cand
vrem sa trecem de la un tip mai mare la unul mai mic exista posibilitatea pierderii de
date.
OOP

Daca afisam variabila d2 ce valoare credeti ca are, avand in vedere ca este de tipul
double?

double d1 = 10;
int i1 = (int) d1;
double d2 = i1;
System.out.println(d2);
OOP

Daca afisam variabila d2 ce valoare credeti ca are, avand in vedere ca este de tipul
double?

double d1 = 10;
int i1 = (int) d1;
double d2 = i1;
System.out.println(d2); //10.0
OOP

Acum sa facem acelasi test, doar ca vom asigna variabile d1 valoarea 10.99.
Ce valoare va avea d2 la final?

double d1 = 10.99;
int i1 = (int) d1;
double d2 = i1;
System.out.println(d2);
OOP

Valoarea lui d2 este 10.0. Prin conversia la int s-a pierdut informatia zecimala.
OOP

Byte este un tip de date pe 8 biti. Asta inseamna ca poate stoca pana la 2 la puterea a 8-a numere.
2 la puterea a 8-a este egal cu 256. Pentru ca byte accepta si numere pozitive si numere negative, atunci 256
se imparte in mod egal si astfel se obtin 128 de numere negative si 128 de numere pozitive.
Este usor sa testam acest lucru astfel:
byte b1 = Byte.MAX_VALUE;
byte b2 = Byte.MIN_VALUE;
System.out.println("Byte ia valori intre " + b2 + " si " + b1); //Byte ia valori intre -128 si 127

Valoarea maxima pe care o poate tine un byte este 127.


Ce se intampla daca avem o variabila de tip int cu valoarea 130 si vrem sa o stocam intr-o variabila de tip byte
(care este mai mica)?

int i = 130;
byte b3 = (byte) i;
System.out.println(b3); //-126

int i = 258;
byte b3 = (byte) i;
System.out.println(b3);//2
OOP

Upcasting

Putem face cast de la un tip la altul nu doar intre primitive si clasele Wrapper din Java sau
clasa String, ci si intre clasele scrise chiar de noi.

Mostenirea este strans legata de upcasting.


Procedeul de conversie de la o subclasa la o superclasa se numeste upcasting.
Upcasting-ul este facut automat de compilator.
OOP

//parent class
public class Flower {
//...
}

//child class of Flower


public class GardenFlower extends Flower {
//...
}

//gardenFlower este o referinta de tip GardenFlower ce refera un obiect al clasei GardeFlower


GardenFlower gardenFlower = new GardenFlower();
//datorita relatiei de mostenire, putem asigna referinta gardenFlower unei referinte de tip Flower
//conversia la tipul Flower se face automat deoarece GardenFlower este un subtip al lui Flower
Flower flower = gardenFlower;
//puteam de asemenea sa facem conversia si explicit, dar un IDE inteligent de atentioneaza ca acest cast este
redundant
Flower anotherFlower = (Flower) gardenFlower;
OOP

Downcasting

Daca avem nevoie sa folosim o variabila cu tipul Flower pentru a apela o metoda disponibila doar in
clasa GardenFlower?
Putem face asta cu ajutorul downcasting. Downcasting reprezinta conversia de la o clasa parinte la o
clasa copil.

//gardenFlower este declarata cu tipul Flower, dar refera un obiect de tipul GardenFlower.
//putem face asta pentru ca Flower si GardenFlower sunt inrudite (GardenFlower o mosteneste pe Flower, este un
subtip al lui Flower)
Flower gardenFlower = new GardenFlower();

//pentru a putea apela metoda smellsGood() din clasa GardenFlower, e necesar sa facem un cast
((GardenFlower) gardenFlower).smellsGood();
OOP

In proiectele complexe, inainte de a face downcast de la un tip la alt tip,


este comun sa folosim operatorul instanceof.
Operatorul instanceof ne ajuta sa verificam daca un obiect este o
instanta a unui anumit tip de date (clasa, subclasa, interfata).

Verificarea returneaza un boolean: true sau false.


OOP

Flower flower = new Flower();


GardenFlower gardenFlower = new GardenFlower();

//verificam daca variabila flower este instanta a clasei Flower


System.out.println(flower instanceof Flower); //true
//verificam daca variabila gardenFlower este instanta a clasei GardenFlower
System.out.println(gardenFlower instanceof GardenFlower); // true

//verificam daca variabila gardenFlower este instanta a clasei Flower care este parinte pentru GardenFlower
System.out.println(gardenFlower instanceof Flower); // true
//verificam daca variabila flower este instanta a clasei GardenFlower
System.out.println(flower instanceof GardenFlower); // false
OOP

Dar urmatoarea linie, ce credeti ca va afisa?

System.out.println(flower instanceof Object);


Recapitulare
OOP

Ce este o interfata?
OOP

Ce este o interfata?

O interfata este un tip de date abstract ce defineste o lista


de metode publice abstracte pe care orice clasa care
implementeaza interfata este obligata sa le implementeze.
OOP

Ce tipuri de metode poate contine o interfata?


OOP

Ce tipuri de metode poate contine o interfata?

1. Metode abstracte.
2. Metode default
3. Metode statice
OOP

Care este relatia dintre o interfata si clasa care


o implementeaza?
OOP

Care este relatia dintre o interfata si clasa care


o implementeaza?

IS.
OOP

Car IS Movable
Glass IS Breakable
Dog IS Lovable
Book IS Readable
Exemple
Interfata indica un comportament al clasei care o
implementeaza.
Putem sa avem si clase si interfete denumite astfel:
Dog IS CanWalk
Bird IS CanSing
Unde IS se inlocuieste cu implements.

Sau mai putem avea:


Bicycle IS Vehicle
Circle IS GeometricFigure

De asemenea este comun ca in aplicatiile cu un


anumit tip de arhitectura sa avem interfete cu
denumiri ca:
PersonService
VehicleInformationService
RemoteControlService
OOP

Care este contractul dintre o clasa si o


interfata?
OOP

Care este contractul dintre o clasa si o


interfata?

O clasa care implementeaza o interfata va implementa


metodele abstracte definite in interfata.
OOP

Este o problema in acest cod? (poate fi corect)

public class Readable {


public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

public class Readable {


public boolean isPrinted();
} o clasa nu poate avea metode abstracte.
OOP

Este o problema in acest cod? (poate fi corect)

public interface class Readable {


public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

public interface class Readable {


public boolean isPrinted();
} cuvantul class este in plus, trebuie sa-l scoatem ca sa
compileze.
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


public boolean isPrinted();
} interfata este definita corect, codul compileaza
OOP

Este o problema in acest cod? (poate fi corect)

public final interface Readable {


public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

public final interface Readable {


public boolean isPrinted();
} o interfata nu poate fi final.
OOP

Este o problema in acest cod? (poate fi corect)

interface Readable {
public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

interface Readable {
public boolean isPrinted();
} interfata este definita corect, codul compileaza
OOP

Este o problema in acest cod? (poate fi corect)

protected interface Readable {


public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

protected interface Readable {


public boolean isPrinted();
} o interfata nu poate fi definita ca protected sau private. By
default este publica.
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


private static int NUMBER_OF_PAGES = 300;

public boolean isPrinted();


}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


private static int NUMBER_OF_PAGES = 300;
variabilele dintr-o interfata sunt public static final
public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


int NUMBER_OF_PAGES = 300;

public boolean isPrinted();


}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


int NUMBER_OF_PAGES = 300;
codul este corect deoarece specificatorii “public static
public boolean isPrinted(); final” sunt asumati, compilatorul ii pune automat. Noi ii
} putem omite pe toti sau doar pe unii dintre ei.
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


int NUMBER_OF_PAGES = 300;
public static final Boolean HAS_COVERS;

public boolean isPrinted();


}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


int NUMBER_OF_PAGES = 300;
public static final Boolean HAS_COVERS; Variabila HAS_COVERS nu a fost initializata, codul nu va
compila.
public boolean isPrinted();
}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


public boolean isPrinted();

public int getAverageNumberOfPages() {


return 300;
}
}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


public boolean isPrinted();
metoda getAverageNumberOfPages nu va compila
public int getAverageNumberOfPages() { deoarece este o metoda concreta si ii lipseste cuvantul
return 300; cheie “default” sau cuvantul cheie “static”.
}
}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


public boolean isPrinted();

public default int


getAverageNumberOfPages() {
return 300;
}
}

public class Main {


public static void main(String[] args) {
Readable book = new Readable();
}
}
OOP

Este o problema in acest cod? (poate fi corect)

public interface Readable {


public boolean isPrinted();
Readable este interfata, iar interfetele nu pot fi instantiate.
public default int
getAverageNumberOfPages() {
return 300;
}
}

public class Main {


public static void main(String[] args) {
Readable book = new Readable();
}
}
OOP

Dar daca modificam clasa Main astfel:

public interface Readable {


public boolean isPrinted();

public default int


getAverageNumberOfPages() {
return 300;
}
}

public class Main {


public static void main(String[] args) {
Readable book;
}
}
OOP

Dar daca modificam clasa Main astfel:

public interface Readable {


public boolean isPrinted();
codul compileaza, dar momentan nu putem face nimic cu
public default int book. Codul este incomplet, dar nu este gresit.
getAverageNumberOfPages() {
return 300;
}
}

public class Main {


public static void main(String[] args) {
Readable book;
}
}
OOP

Cand folosim clase abstracte si cand folosim


interfete?
OOP

Cand folosim clase abstracte si cand folosim Folosim o clasa abstracta atunci cand:
interfete? - relatia dintre clasa abstracta si clasa concreta este IS-A,
(Dog is an Animal)
- reutilizam o serie metode si campuri din aceasta clasa in
clasele derivate.
- avem acelasi comportament dar si aceeasi implementare
a unui comportament in mai multe clase

Folosim o interfata atunci cand:


- vrem sa avem doar o descriere a structurii, fara
implementari
- avem doar acelasi compotament in mai multe clase dar
nu si aceeasi implementare a lui
- relatia dintre interfata si clasa care o implementeaza este
IS (Car is Movable)
OOP

Ce este compozitia?
OOP

Ce este compozitia?
Compozitia este conceptul prin care putem implementa o
relatie de HAS-A intre doua clase.
Compozitia este o asociere intre doua obiecte distincte.

Asocierea poate fi de 4 feluri:


1. one-to-one: Country – President
2. one-to-many: Country – City
3. many-to-one: City – Country
4. many – to – many: Country – Currency (euro)
OOP

De ce folosim compozitia?
OOP

De ce folosim compozitia?

Asemenea mostenirii, folosim compozitia pentru a reutiliza


cod si pentru a avea un design software cat mai simplu.
OOP

Cum implementam compozitia?


OOP

Cum implementam compozitia?

Implementam compozitia prin declararea unor


obiecte ca variabile de instanta, campuri.
OOP

Cand si de ce folosim compozitia?


OOP

Cand si de ce folosim compozitia?

Folosim compozitia atunci cand vrem:


- sa reutilizam cod;
- sa aratam ca relatia dintre doua clase este HAS-A;
- sa avem un design software cat mai simplu.
OOP

Ce este polimorfismul?
OOP

Ce este polimorfismul?

Polimorfismul reprezinta capacitatea obiectelor de a


lua mai multe forme.
OOP

De ce obiectele din Java sunt polimorfice?


OOP

De ce obiectele din Java sunt polimorfice?

Toate obiectele Java sunt polimorfice deoarece trec


testul IS-A cu propriul tip, dar si cu clasa Object.
OOP

Care este cea mai comuna utilizare a


polimorfismului?
OOP

Care este cea mai comuna utilizare a


polimorfismului?

Cea mai comuna utilizare de polimorfism este atunci


cand folosim o referinta cu tipul clasei parinte
pentru a ne referi la un obiect al clasei copil.
OOP

Care sunt cele doua tipuri de polimorfism?


OOP

Care sunt cele doua tipuri de polimorfism?

1. Polimorfismul compile-time (polimorfism


parametric sau polimorfism static)
2. Polimorfismul runtime (polimorfism de
mostenire)
OOP

Cum obtinem polimorfismul compile-time?


OOP

Cum obtinem polimorfismul compile-time?

Polimorfismul compile-time este obtinut prin


supraincarcarea metodelor.
OOP

Ce este supraincarcarea?
OOP

Ce este supraincarcarea?

Supraincarcarea este procedeul prin care putem


avea mai multe metode cu acelasi nume in aceeasi
clasa, dar cu semnaturi diferite.
OOP

Cum obtinem polimorfismul runtime?


OOP

Cum obtinem polimorfismul runtime?

Polimorfismul runtime este obtinut prin


suprascrierea metodelor.
OOP

Ce este suprascrierea?
OOP

Ce este suprascrierea?

Suprascrierea este capacitatea unei subclase de a


avea o implementare specifica a unei metode deja
existente in superclasa.
OOP

Cand se considera ca o metoda este


suprascrisa?
OOP

Cand se considera ca o metoda este


suprascrisa?

Cand o metoda din subclasa are aceeasi semnatura


si acelasi tip returnat ca metoda din superclasa
atunci spunem despre metoda din subclasa ca
suprascrie metoda din superclasa.
OOP

Care sunt cele doua tipuri de variabile din Java?


OOP

Care sunt cele doua tipuri de variabile din Java?

Primitive si referinte.
OOP

Care sunt cele 8 tipuri de date primitive?


OOP

Care sunt cele 8 tipuri de date primitive?

byte - 8 bits
short - 16 bits
char - 16 bits
int - 32 bits
float - 32 biti
long - 64 biti
double - 64 biti
boolean - nu este numeric, poate lua valorile true
sau false
OOP

In functie de ce anume consideram ca un tip de


date primitiv este mai mare sau mai mic decat
alt tip de date primitiv?
OOP

In functie de ce anume consideram ca un tip de


date primitiv este mai mare sau mai mic decat
alt tip de date primitiv? In functie de numarul de biti alocati la declararea
variabilei.
OOP

Cum se face conversia de la un tip de date mai


mare la unul mai mic?
OOP

Cum se face conversia de la un tip de date mai


mare la unul mai mic?
Trebuie sa facem cast la tipul de date mai mic.
OOP

De ce trebuie sa facem cast manual?


OOP

De ce trebuie sa facem cast manual?

Deoarece exista riscul sa pierdem informatie.


OOP

Cum se face conversia de la un tip de date mai


mic la unul mai mare?
OOP

Cum se face conversia de la un tip de date mai


mic la unul mai mare?
Conversia se face automat, nu e nevoie sa o faca
programatorul.
OOP

Ce este o clasa wrapper?


OOP

Ce este o clasa wrapper?

O clasa wrapper este o clasa al carei obiect contine


o primitiva.
OOP

Cate clase wrapper sunt?


OOP

Cate clase wrapper sunt?

Opt clase wrapper, cate una pentru fiecare


primitiva.
byte - Byte
short - Short
char - Character
int - Integer
float - Float
long - Long
double - Double
boolean – Boolean
OOP

Cum se numesc procedeele de conversie de la o


primitiva la clasa wrapper asociata si invers?
OOP

Cum se numesc procedeele de conversie de la o


primitiva la clasa wrapper asociata si invers?
Boxing si unboxing.
OOP

Aceste procedee se fac automat sau trebuie sa


specifice programatorul ca vrea sa converteasca
de la int la Integer, de exemplu?
OOP

Aceste procedee se fac automat sau trebuie sa


specifice programatorul ca vrea sa converteasca
de la int la Integer, de exemplu? Se fac automat.
OOP

Cum procedam daca vrem sa convertim o


variabila cu tipul Integer la tipul String?
OOP

Cum procedam daca vrem sa convertim o


variabila cu tipul Integer la tipul String?
Cu ajutorul metodei toString() pe care o apelam pe
referinta de tip Integer.
OOP

Cum procedam daca vrem sa convertim o


variabila cu tipul int la tipul String?
OOP

Primitivele nu au metode, deci nu putem apela metoda


toString() pentru o variabila de tipul int.
Cum procedam daca vrem sa convertim o Putem in schimb sa facem boxing la clasa wrapper Integer si
variabila cu tipul int la tipul String? apoi sa apelam toString().
int a = 0;
Integer b = a;
String str = b.toString();
Sau ne putem folosi de metoda statica toString ce primeste
ca parametru un int si returneaza o valoare de tip String,
metoda ce se regaseste in clasa wrapper Integer.
int a = 0;
String str = Integer.toString(a);

Aceasta metoda exista si in alte clase wrapper, de exemplu in


clasa Double si o putem folosi astfel:
String strFromDouble = Double.toString(10.02);
Sau
String strFromChar = Character.toString('c');
OOP

Exista 4 reguli pe care Java le aplica intr-o


anumita ordine in cazul operatiilor aritmetice.
Care sunt regulile respective?
OOP

Exista 4 reguli pe care Java le aplica intr-o


anumita ordine in cazul operatiilor aritmetice.
Care sunt regulile respective?
1. daca unul dintre operanzi este double, celalalt operand va
fi promovat la tipul double
2. altfel, daca unul din operanzi este float, atunci si celalalt
operand va fi promovat la tipul float
3. altfel, daca unul din operanzi este long, atunci si celalalt
operand va fi promovat la tipul long
4. altfel, ambii operanzi sunt considerati de tipul int
OOP

Ce este upcasting?
OOP

Ce este upcasting?

Upcasting este procedeul de conversie de la o subclasa la o


superclasa.
OOP

Ce legatura trebuie sa existe intre doua clase ca


sa putem aplica upcasting?
OOP

Ce legatura trebuie sa existe intre doua clase ca


sa putem aplica upcasting?

O legatura de mostenire, una dintre clase trebuie sa fie


copilul celeilalte.
OOP

Care este procedeul invers al lui upcasting?


OOP

Care este procedeul invers al lui upcasting?

Downcasting.
OOP

Si ce reprezinta downcasting?
OOP

Si ce reprezinta downcasting?

Downcasting este procedeul de conversie de la o superclasa


la o subclasa.
OOP

Ce operator trebuie folosit inainte de a face


downcasting?
OOP

Ce operator trebuie folosit inainte de a face


downcasting?

Operatorul instanceof.
OOP

Ce verificam cu ajutorul lui instanceof?


OOP

Ce verificam cu ajutorul lui instanceof?

Verificam daca un obiect este o instanta a unui anumit tip de


date.
OOP

Ce tip de date returneaza verificarea cu ajutorul


lui instanceof?
OOP

Ce tip de date returneaza verificarea cu ajutorul


lui instanceof?

Returneaza un boolean (una din valorile true sau false).


OOP

Nested Classes
OOP

Nested class este o clasa declarata in interiorul altei clase sau interfete.
OOP

O clasa are campuri si metode care reprezinta membrii clasei.


In plus, o clasa poate contine o alta clasa. Clasa continuta se numeste inner
class (clasa interioara) sau nested si este tot un membru al clasei din care face
parte.
OOP

Clasele nested sunt folosite pentru a putea grupa clase si/sau interfete intr-un singur loc.
OOP

Sintaxa:
class MyClass {
//code
class MyInnerClass {
//code
}
}
OOP

Clasa care contine o clasa inner (interioara) se numeste clasa outer (exterioara).
OOP

Clasele inner (sau nested) pot fi statice sau non-statice.


OOP

1. Static Nested Classes

O clasa nested statica este o clasa interioara ce are asociat specificatorul static, asadar este un
membru static al clasei din care face parte.

O clasa nested statica poate fi accesata fara a instantia clasa outer.

La fel ca membrii statici, o clasa nested statica nu are acces la variabilele de instanta si la metodele
clasei outer.

Sintaxa
class MyClass {
//fields
static class MyInnerClass {
//code
}
//methods
}
OOP

2. Non-Static Nested Classes

O clasa nested non-statica poate fi de trei feluri:


2A.) Inner Class
2B.) Method-local Inner Class
2C.) Anonymous Inner Class
OOP

2A.) Clasa inner

Spre deosebire de o clasa normala, o clasa inner poate fi declarata cu


modificatorii de acces private si protected.

Daca o clasa inner este private, atunci ea nu poate fi accesata din exteriorul
clasei outer.
OOP

2B.) Method-local Inner Class

In Java putem scrie o clasa in interiorul unei metode. Clasele create in interiorul
unei metode se numesc local inner classes. Metoda apartine clasei outer.

La fel ca variabilele locale (variabile declarate in interiorul unei metode), scopul


unei clase inner este restrictionat la metoda in care este declarata.
Pentru a apela metodele dintr-o clasa inner locala, trebuie sa instantiem clasa in
interiorul metodei.
OOP

2C.) Anonymous Inner Classes

Clasele anonime ne ajuta sa facem codul mai concis.


Acestea ne permit sa declaram si sa instantiem o clasa in acelasi timp.
Sunt ca niste clase locale, cu exceptia faptului ca nu au un nume.
Le folosim atunci cand trebuie sa utilizam o clasa locala o singura data.

O clasa anonima este o expresie.


OOP

Folosim clase nested atunci cand vrem sa grupam logic clase folosite intr-un singur loc.
Daca o clasa este folosita doar intr-o alta clasa, atunci ar fi logic sa o includem in clasa respectiva
pentru a le avea pe amandoua in acelasi loc.
Aceasta arhitectura ar putea face codul mai usor de citit si de mentinut.
OOP

Folosirea claselor nested sporesc incapsularea astfel:


- sa consideram doua clase A si B
- clasa B are nevoie de acces la membrii clasei A
- din cauza aceasta trebuie sa declaram membrii clasei A cu un modificator de acces altul decat
private pentru a putea fi accesibili din exteriorul clasei

Avantajele ascunderii clasei B in interiorul clasei A ar fi urmatoarele:


- nu avem acces la implementarea clasei B din exterior
- membrii clasei A pot fi declarati private, iar B ar putea sa-i acceseze fiind o clasa inner
OOP

Compararea obiectelor
OOP

Compararea a doua obiecte se poate face folosind metoda equals().


Insa aceasta comparatie ne spune doar daca obiectele sunt egale sau nu.
OOP

Intr-o structura de date putem avea obiectele intr-o anumita ordine.


Pentru a ordona obiectele trebuie sa le putem compara intre ele astfel incat sa
putem stabili daca un obiect este mai mic, mai mare sau egal cu altul.
OOP

Clasa String din Java implementeaza interfata Comparable si suprascrie metoda compareTo(String
str) de aceea putem compara doua String-uri intre ele.

String greet1 = “hello”;


String greet2 = “hi”;
greet1.compareTo(greet2); //-4 - pentru ca va compara valoarea fiecarui caracter din primul
String transformata in codul sau unicode cu valorile caracterelor din celalalt String.

String greet3 = “hello”


greet1.compareTo(greet3); //0

Daca String-urile au aceleasi caractere returneaza 0, iar daca am compara aceleasi String-uri cu
metoda equals() am primi raspuns true.
OOP

Daca avem un Array de String putem sorta structura de date


folosind Array.sort(numele_array-ului).

Acest lucru este posibil datorita faptului ca String implementeaza


interfata Comparable si suprascrie metoda compareTo(String
anotherString) ceea ce face posibila sortarea array-ului nostru in
ordine alfabetica.
OOP

Putem folosi metoda sort() a clasei Array si pentru alte tipuri de date din Java, atat pentru
primitive, clase din limbaj (Integer, Boolean, etc.) sau pentru clase create de noi.

int[] numbers = new int[]{9,7,6,2,1,2,4,4,10,2,10,20};


Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers)); //[1, 2, 2, 2, 4, 4, 6, 7, 9, 10, 10, 20]
OOP

Pentru a folosi metoda sort() pentru clasele create de noi acestea trebuie sa implementeze
interfata Comparable si metoda compareTo(). Implementarea metodei compareTo() o scriem noi
in functie de necesitati.
OOP

Folosind interfata Comparable implementarea metodei compareTo este tight-coupled (strans


legata) de clasa comparata si nu putem avea decat o singura implementare a metodei
compareTo().
OOP

Un alt mod prin care putem realiza compararea obiectelor


este prin utilizarea interfetei Comparator.
OOP

Folosind Comparator putem avea oricate implementari ale


interfetei pentru o clasa, astfel putem compara de fiecare
data in functie de alta proprietate in functie de necesitati.
OOP

Avand in vedere aspectele anterior mentionate pentru a


compara doua obiecte de acelasi tip este de preferat sa
folosim interfata Comparator.
OOP

Interfata Comparator nu va fi implementata de clasa comparata ci de o noua clasa al carei


obiecte vor avea ca scop compararea clasei data in definitia noii clase:

Exemplu:
public class EmployeeNameComparator implements Comparator<Employee> {
...
}
OOP

Acest tip de implementare a Comparator este loose-coupled (decuplata) de clasa comparata si


putem avea oricate clase de tip Comparator avem nevoie pentru o clasa pe care vrem sa o
comparam. De exemplu putem avea pentru o clasa Employee, o clasa care implementeaza
Comparator si care compara numele angajatilor, o alta clasa care implementeaza Comparator
care compara salariul angajatilor, etc.
OOP

public class EmployeeSalaryComparator implements Comparator<Employee> {


@Override
public int compare(Employee o1, Employee o2) {
return o1.getSalary() - o2.getSalary();
}
}

Employee employee1 = new Employee("John", 30000);


Employee employee2 = new Employee("Mike", 15000);
EmployeeSalaryComparator employeeSalaryComparator = new EmployeeSalaryComparator();
System.out.println(employeeSalaryComparator.compare(employee2, employee1) > 0); //false
OOP

Obiectele de tip Comparator pot fi date si ca parametru metodei


Array.sort(array, comparator) pentru a sorta o structura de date.
OOP

Atat Comparator cat si Comparable pot fi folosite si


cu alte structuri de date precum List, Set etc.
OOP

Generics
OOP

Java Generics au fost introduse in Java 1.5 cu scopul de a adauga un strat


suplimentar de abstractizare peste tipurile de date.
OOP

Mai mult decat atat, Generics au fost introduse pentru a adauga mai
multa stabilitate proiectelor complexe si pentru a reduce numarul de
posibile bug-uri ce au loc la runtime, eliminand necesitatea de a face
cast.
OOP

Avem o metoda generica care primeste ca parametru un array de tip T (T poate fi orice tip de date) si
care afiseaza elementele array-ului.

public <T> void displayArray(T[] arr) {


for (T element : arr) {
System.out.println(element);
}
}

In Java exista "generic methods" care sunt metode ce au o singura semnatura, dar pot fi apelate cu
argumente de tipuri diferite.
Compilatorul asigura corectitudinea oricaror tipuri de date folosite.
Metodele generice au urmatoarele proprietati:
- metodele generice au inainte de return type un asa-zis type parameter
- type parameter este un operator diamond ce include tipul de date
- metodele generice pot avea mai multe tipuri de parametri in signatura separate prin virgula
- corpul metodei generice este similar unei metode normale.
OOP

Garbage Collection
OOP

Garbage Collection este un proces care sterge din memorie obiectele care nu mai sunt folosite.
OOP

Java stie ca un obiect nu va mai fi folosit atunci cand referinta sa este


out of scope (blocul de cod unde aceasta a fost definit a terminat
executia) sau atunci cand nu mai exista o referinta valida catre acel
obiect (referintele obiectelor sunt null sau refera alte obiecte).

public void process(){


Object o = new Object();
Object o2 = new CustomObject();
o2 = null; //new CustomObject(); este eligibil pentru stergere
}
//new Object(); este eligibil pentru stergere deoarece referinta o este
out-of-scope
OOP

Garbage Collection ruleaza atunci cand procesorul este liber sau atunci
cand memoria Heap este aproape plina.
Nu ii putem spune noi cand sa ruleze dar ii putem sugera cu
System.gc();
OOP

Garbage Collection functioneaza in doi pasi:


- Mark – identifica zonele de memorie folosite si nefolosite
- Sweep – sterge obiectele identificate ca fiind nefolosite
OOP

In JVM gasim mai multe implementari ale Garbage Collectorului


despre care puteti invata mai multe de aici:

https://www.baeldung.com/jvm-garbage-collectors
OOP

Imutabilitatea
OOP

Imutabilitatea este conceptul prin care restrictionam modificarea starii


unui obiect dupa ce aceasta a fost initializat.
OOP

Incapsularea restrictioneaza accesul nedorit al obiectelor, insa prin


imutabilitate restrictionam complet modificarea unui obiect.
OOP

Imutabilitatea ne asigura ca un obiect odata


creat nu va mai fi modificat ulterior.
OOP

Obiectele imutabile sunt thread-safe, deci pot fi folosite de


multiple threaduri fara a avea anomalii de scriere sau citire.

De asemenea obiectele imutabile pot fi folosite ca si obiecte


cheie in colectii de tip Map.
OOP

Dezavantajul folosirii obiectelor imutabile ar fi ca nu pot fi


refolosite cu alte informatii ceea ce creaza multe obiecte eligibile
pentru stergere de catre Garbage Collection.
OOP

Clasa String din Java este un exemplu de obiect imutabil. De


fiecare data cand incercam sa modificam un String in memorie
se genereaza un alt obiect cu noua valoare, vechea valoare fiind
eligibila pentru stergere de catre Garbage Collection.
OOP

String str1 = "hello";


str1.toUpperCase();

//Ce va afisa urmatoarea linie de cod?


System.out.println(str1);
OOP

String str1 = "hello";


str1.toUpperCase();

//Ce va afisa urmatoarea linie de cod?


System.out.println(str1); //hello

Apelul metodei toUpperCase() al clasei String nu modifica obiectul str1. Clasa String
fiind imutabila, inseamna ca obiectul str1 nu poate fi modificat.
Metoda toUpperCase() returneaza un alt obiect cu valoarea “HELLO”.
Obiectul “HELLO” este eligibil pentru Garbage Collection deoarece in exemplul anterior
acest obiect nu este referit.
OOP

String str1 = "hello";


str1 = str1.toUpperCase();

//Ce va afisa urmatoarea linie de cod?


System.out.println(str1);
OOP

String str1 = "hello";


str1 = str1.toUpperCase();

//Ce va afisa urmatoarea linie de cod?


System.out.println(str1); //HELLO

In acest exemplu String-ul “hello” nu va mai fi referit si va fi eligibil pentru stergere de


catre Garbage Collection iar referinta str1 va referi un nou obiect “HELLO”.
OOP

In afara de clasele/obiectele imutabiledin limbajul Java putem crea si propriile clase pe


baza carora sa instantiem obiecte imutabile.
OOP

Cum initializam starea unui obiect de la declarare?


OOP

Folosind un constructor cu parametrii care initializeaza campurile obiectului.


OOP

Cum putem modifica starea obiectului dupa initializare?


OOP

Folosind metode setter. Insa exista si ale moduri prin care


putem modifica starea unui obiect cum ar fi alte metode sau
chiar metodele getter.
OOP

Cum putem limita modificarea starii unui obiect dupa


initializare?
OOP

Reguli pentru a crea un obiect imutabil:


- Omitem setterii
- Campurile/starea obiectului trebuie sa fie declarate cu specificatorul private
- Clasa trebuie sa fie final, astfel eliminam posibilitatea ca ea sa fie extinsa
- Tipul de date returnat de getteri sa fie imutabil sau sa returnam o copie
Recapitulare
OOP

Ce este o clasa nested?


OOP

Ce este o clasa nested?

O clasa nested este o clasa declarata in interiorul altei


clase.
OOP

Cand si de ce folosim clase nested?


OOP

Cand si de ce folosim clase nested?

Clasele nested sunt folosite pentru a putea grupa clase


si/sau interfete intr-un singur loc facand codul mai usor de
citit si de intretinut.
OOP

De cate tipuri pot fi clasele inner?


OOP

De cate tipuri pot fi clasele inner?

Clasele inner (sau nested) pot fi statice sau non-statice.


OOP

De cate tipuri pot fi clasele inner non statice?


OOP

De cate tipuri pot fi clasele inner non statice?

2A.) Inner Class


2B.) Method-local Inner Class
2C.) Anonymous Inner Class
OOP

Pot exista clase cu modificator de access private


sau protected?
OOP

Pot exista clase cu modificator de access private


sau protected?

Da, dar trebuie sa fie inner classes.


OOP

Pot exista clase cu specificator static?


OOP

Pot exista clase cu specificator static?

Da, dar trebuie sa fie inner classes.


OOP

Prin cate moduri putem compara un obiect?


OOP

Prin cate moduri putem compara un obiect?

Prin 3 moduri:
- folosind metode equals() (putem verifica daca doua
obiecte sunt egale sau nu)
- implementand interfata Comparable
- implementand interfata Comparator

Implementand Comparator sau Comparable putem vedea


daca un obiect este mai mic, mai mare sau egal cu un obiect
de acelasi tip.
OOP

Care modalitatea de preferat prin care putem


compara doua obiecte?
OOP

Care modalitatea de preferat prin care putem


compara doua obiecte?

Folosind o implementare a interfetei Comparator, codul


nostru este loose-coupled (decuplat) si putem avea cate un
obiect care implementeaza Comparator pentru fiecare
dintre proprietatile obiectului.
OOP

La ce folosesc Generics?
OOP

La ce folosesc Generics?

Folosind Generics putem scrie metode reutilizabile cu mai


multe tipuri de date, eliminand necesitatea de a face cast.

Cele mai importante beneficii introduse de generics sunt:


- eliminarea codului duplicat
- eliminarea eventualelor erori de casting
OOP

Ce este Garbage Collection?


OOP

Ce este Garbage Collection?

Garbage Collection este un proces care sterge din memorie


obiectele care nu mai sunt folosite.
OOP

In Java, cand este un obiect eligibil pentru a fi


sters din memorie?
OOP

In Java, cand este un obiect eligibil pentru a fi


sters din memorie?

Java stie ca un obiect nu va mai fi folosit atunci cand referinta


sa este out of scope (blocul de cod unde aceasta a fost definit
a terminat executia) sau atunci cand nu mai exista o referinta
valida catre acel obiect (referintele obiectelor sunt null sau
refera alte obiecte).
OOP

Cand este executat Garbage Collectorul?


OOP

Cand este executat Garbage Collectorul?

Garbage Collection ruleaza atunci cand procesorul este liber


sau atunci cand memoria Heap este aproape plina.
Nu ii putem spune noi cand sa ruleze dar ii putem sugera cu
System.gc();
OOP

Ce este Imutabilitatea?
OOP

Ce este Imutabilitatea?

Imutabilitatea este conceptul prin care restrictionam


modificarea starii unui obiect dupa ce aceasta a fost initializat.
OOP

Care este diferenta dintre Imutabilitate si


Incapsulare?
OOP

Care este diferenta dintre Imutabilitate si


Incapsulare?

Incapsularea restrictioneaza accesul nedorit al obiectelor, insa


prin imutabilitate restrictionam complet modificarea unui
obiect.
OOP

Care sunt regulile pentru a crea un obiect


imutabil?
OOP

Care sunt regulile pentru a crea un obiect


imutabil?

- Omitem setterii
- Campurile/starea obiectului trebuie sa fie declarate
cu
specificatorul private
- Clasa trebuie sa fie final, astfel eliminam posibilitatea
ca ea sa
fie extinsa
- Tipul de date returnat de getteri sa fie imutabil sau sa
returnam
o copie
Collections
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Structuri de date
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Structurile de date reprezinta o modalitate de a stoca si


organiza informatia astfel incat sa fie utilizata in mod eficient.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Array-urile sunt o colectie de elemente stocate secvential


(unul dupa altul). Aceasta organizare de elemente este
realizata cu ajutorul structurilor de date.

In limbajul de programare Java mai exista si alte modalitati de a


organiza datele in memorie.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Tipurile de structuri de date sunt:

- structuri de date primitive: acestea sunt chiar tipurile de date


primitive (int, char, float, etc.) care stocheaza o singura valoare.

- structuri de date non-primitive.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Structurile de date non-primitive sunt la randul lor de doua feluri:

- lineare: datele sunt stocate intr-o maniera secventiala


(Arrays, Linked list, Stacks, Queues)

- non-lineare (Trees)
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Structurile de date mai pot fi clasificate si dupa felul in care este


alocata memoria:

- statice: dimensiunea structurii de date este alocata la compile time,


deci dimensiunea este fixa.
- dinamice: dimensiunea structurii de date este alocata la run time,
asadar dimensiunea este flexibila.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Operatiile pe care le putem performa pe structurile de date includ:

- cautarea unui element


- sortarea structurii de date in ordine ascendenta/descendenta
- inserarea unui element
- modificarea unui element
- stergerea unui element
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Structuri de date din limbajul Java:

Array, Linked List. Stack. Queue, etc.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Avantajele utilizarii structurilor de date:

- codul scris poate fi mai eficient din punct de vedere la timpului


consumat si al spatiului utilizat daca utilizam structurile de date
optime;

- structurile de date pot fi reutilizate => reutilizarea face ca


programul sa fie mai performant;

- structurile de date au un nivel de abstractizare in sensul in care


clientul ce utilizeaza structurile de date nu cunoaste
implementarea, are acces doar la interfata si la metodele oferite de
aceasta, fara sa stie de fapt cum se petrec lucrurile in spate.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Collections framework
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Collections framework este un set de interfete, implementari si


algoritmi (metode pentru sortare, cautare, etc.).

Collections framework implementeaza cele mai importante structuri


de date abstracte.

Este mai mult o librarie decat un framework.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Colectiile sunt grupuri de obiecte tratate ca o entitate. Unele dintre ele


pot sa inlocuiasca Array.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

De retinut este faptul ca nu putem adauga primitive in colectii, ci doar obiecte.

Primitivele vor fi automat convertite in clasele lor wrapper,


int -> Integer, boolean -> Boolean, etc.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cele mai importante colectii sunt reprezentate prin interfetele:


List, Queue, Set, Map (chiar daca nu este o subinterfata a interfetei Collections)
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

List
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Principalele particularitati ale interfetei List:

→ elemente sunt ordonate si sunt accesibile folosindu-ne de un index


→ se pastreaza ordinea inserarii
→ poti adauga la o pozitie specificata, doar daca pe aceasta pozitie exista
deja un element sau null
→ daca pozitia nu e specificata, elementul va fi adaugat la coada

Implementarile interfetei List pot sa inlocuiasca Array-urile, fiind mai eficiente


si dinamice. Daca unui Array trebuie sa-i specificam dimensiunea si aceasta
nu poate fi modificata ulterior, unui ArrayList nu trebuie sa-i specificam
dimensiunea de la declarare, aceasta putand avea 0 sau mai multe elemente.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cele mai importante implementari ale interfetei List sunt ArrayList si LinkedList
si este bine sa inlocuim Array in codul nostru cu una dintre aceste
implementari pentru un plus de performanta si flexibilitate.

Sintaxa:

ArrayList<String> list = new ArrayList<>();


LinkedList<String> list = new LinkedList<>();
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Este best practice sa ne referim la o colectie folosind referinte de tip abstract.


ArrayList si LinkedList implementeaza List deci putem rescrie astfel:

List<String> list = new ArrayList<>();


List<String> list = new LinkedList<>();
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

ArrayList vs LinkedList

Elementele ambelor colectii sunt accesibile folosindu-ne de un index.

Ambele sunt implementari ale lui List, pastreaza ordinea inserarii, permit duplicate si null.

LinkedList implementeaza si interfata Deque care ii adauga functionalitati extra fata de ArrayList.

Adaugarea si stergerea in LinkedList sunt mai rapide decat pe ArrayList insa cautarea este mai putin
performanta.

Deci folosim ArrayList cand avem mai multe cautari in colectie si LinkedList cand avem adaugari si
stergeri mai frecvente.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum utilizam o colectie de tip List?

Pentru a adauga intr-o colectie de tip List folosim metoda add(Object object).

Pentru a citi un element folosim metoda get(index);

Pentru a citi toate elementele putem folosi blocurile loop, precum for, for-Each sau while pentru a
parcurge colectia la fel cum parcurgem cand folosim Array.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Queue
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Principalele particularitati ale interfetei Queue:

→ similar lui List, este o lista ordonata de elemente, se pastreaza ordinea inserarii
→ este creata pentru ca elementele sa se adauge la coada si sa se stearga/proceseze
de la capat
→ folosita atunci cand vrei sa procesezi elemente in ordinea in care le-ai inserat
→ exista si o subinterfata a lui Queue numita Deque care suporta procesarea de la
ambele capete
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cele mai importante implementari ale interfetei Queue sunt


LinkedList, PriorityQueue, ArrayDeque.

Sintaxa:

Queue<String> pq = new PriorityQueue<>();


Queue<String> ll = new LinkedList<>();
Queue<String> ad = new ArrayDeque<>();
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum utilizam o colectie de tipul Queue?

Pentru a adauga intr-o colectie de tip Queue folosim metoda add(Object object).

Pentru a citi putem folosi blocul for-Each sau un iterator pentru a parcurge colectia.

Elementele interfetei Queue nu sunt accesibile folosindu-ne de un index, dar sunt accesibile folosindu-
ne de metode precum peek() care returneaza primul element din colectie sau poll() care retureaza
primul element din colectie pe care apoi il sterge.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Set
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Principalele particularitati ale interfetei Set:

→ contine doar elemente unice, daca adaugi acelasi element de doua ori, este introdus
doar o data
→ nu garanteaza ordinea elementelor, nu pastreaza ordinea inserarii
→ exista o subinterfata a lui Set, numita SortedSet in care elementele sunt sortate
(foloseste un o implementare a interfetei Comparator, pentru a ordona elementele)
→ exista si o subinterfata a lui SortedSet numita NavigableSet cu metode de navigare
prin colectie
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cele mai importante implementari ale interfetei Set sunt:

→ HashSet (super rapid, nu mentine ordinea adaugarii, nu sunt sortate, sunt adaugate in
functie de valoare hashcode-ului fiecarui element)
→ LinkedHashSet (mentine ordinea inserarii, nu sunt sortate, foloseste hashcode)
→ TreeSet (sortat, implementeaza NavigableSet, deci are metode de navigare in colectie)

Sintaxa:

Set<String> set1 = new HashSet<>();


Set<String> set2 = new LinkedHashSet<>();
Set<String> set3 = new TreeSet<>();
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

List vs Set

Implementarile interfetei List au elementele ordonate, permit elemente duplicat si elementele


sunt accesibile la un index.

Implementarile lui Set au elementele neordonate, insa sunt unice, nu permit duplicat.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum utilizam o colectie de tipul Set?

Pentru a adauga intr-o colectie de tip Set folosim metoda add(Object object).

Pentru a citi putem folosi blocul for-Each sau un iterator pentru a parcurge colectia.

Elementele interfetei Set nu sunt accesibile folosindu-ne de un index.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Map
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Interfata Map nu este o subinterfata a interfetei Collection dar cand ne referim la


Colectii, de obicei includem si interfata Map cu implementarile ei.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Principalele particularitati ale interfetei Map:

→ Map este o lista de cheie/valoare unde cheia este unica


→ exista o subinterfata a lui Map, numita SortedMap in care elementele sunt sortate
dupa cheie (foloseste Comparator)
→ exista si o subinterfata a lui SortedMap numita NavigableMap cu metode de
navigare prin colectie
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce insemna o lista de cheie / valoare?

Map - [ (cheie : valoare), (cheie : valoare), (cheie : valoare), (cheie : valoare), (cheie : valoare) ]
ArrayList - [element, element, element, element], fiecare element fiind accesibil la un index
0 1 2 3

Daca in cazul ArrayList elementele sunt acceasibile la un index numeric 0,1,2,3...n in cazul Map
elementele sunt accesibile printr-o cheie definita de utilizator care poate avea orice tip de date,
String, Integer, tipuri de date custom definite de utilizator precum Employee, User, CustomClass,
etc.

Un map poate avea ca si cheie un Employee si valoare Job


Map - [(Employee : Job), (Employee : Job)]
sau un String ca si cheie si valoare un alt String
Map - [(String : String), (String : String)]
etc.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cele mai importante implementari ale interfetei Map sunt:

→ HashMap (foarte eficient, nu are elementele ordonate sau sortate)


→ TreeMap (sortat in ordine naturala dupa cheie, implementeaza NavigableMap cu metode
de navigare prin colectie, este mai putin performant decat HashMap)
→ LinkedHashMap(ordinea inserarii mentinuta, accesarea elementelor rapida,
stergere/adaugare neperformanta)

Sintaxa:

Map<String, String> map1 = new HashMap<>();


Map<Employee, Integer> map2 = new LinkedHashMap<>();
Map<Employee, Integer> map3 = new TreeMap<>();
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum utilizam o colectie de tipul Map?

Pentru a adauga elemente intr-un map folosim metoda .put(cheie, valoare).

Pentru a accesa un element folosim metoda get(cheie);

Pentru a citi toate elementele folosim un bloc for pentru a itera pe lista de chei obtinute din map.
Apoi pentru fiecare cheie putem accesa valoarea ei.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Pentru a stoca perechi cheie/valoare intr-un HashMap, cheia trece printr-un algoritm de
hashing din care rezulta o valoare numerica in functie de care se va stabili locul perechii
in HashMap.

De aceea fiecare tip de date folosit ca si cheie in HashMap trebuie sa implementeze


metodele equals si hashcode si este best practice ca aceste obiecte sa fie imutabile.

Trebuie sa fie imutabile pentru ca daca se modifica obiectul cheie nu mai poate fi gasita
apoi perechea in HashMap, hashCode-ul generat fiind altul.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS
Recapitulare
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce sunt structurile de date?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce sunt structurile de date?

Structurile de date reprezinta o modalitate


de a stoca si organiza informatia astfel
incat sa fie utilizata in mod eficient.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

De cate tipuri sunt structurile de date non-


primitive?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

De cate tipuri sunt structurile de date non-


primitive?

- lineare: datele sunt stocate intr-o maniera


secventiala (Arrays, Linked list, Stacks,
Queues)
- non-lineare (Trees)
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai cunoscute operatii pe care le


putem realiza pe structurile de date?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai cunoscute operatii pe care le


putem realiza pe structurile de date?
- cautarea unui element
- sortarea structurii de date in ordine
ascendenta/descendenta
- inserarea unui element
- modificarea unui element
- stergerea unui element
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este Collections Framework?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este Collections Framework?

Collections framework este un set de


interfete, implementari si algoritmi (metode
pentru sortare, cautare, etc.).
Collections framework implementeaza cele
mai importante structuri de date abstracte.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce sunt colectiile?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce sunt colectiile?

Colectiile sunt grupuri de obiecte tratate ca


o entitate. Unele dintre ele pot sa
inlocuiasca Array.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Putem avea o colectie de primitive?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Putem avea o colectie de primitive?

Nu, colectiile pot contine doar obiecte.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei List?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei List?

Cele mai importante implementari ale


interfetei List sunt ArrayList si LinkedList.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante subinterfete ale


Collection?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante subinterfete ale


Collection?

List, Queue, Set


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Implementarile interfetei Map sunt structuri de


date?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Implementarile interfetei Map sunt structuri de


date?

Da, Map nu este o subinterfata a lui


Collection.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei List?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei List?


→ elemente sunt ordonate si sunt
accesibile folosindu-ne de un index
→ se pastreaza ordinea inserarii
→ poti adauga la o pozitie specificata, doar
daca pe aceasta pozitie exista deja un
element sau null
→ daca pozitia nu e specificata, elementul
va fi adaugat la coada
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum este stabilit locul unei perechi cheie/valoare


intr-un HashMap?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum este stabilit locul unei perechi cheie/valoare


intr-un HashMap?

Cheia trece printr-un algoritm de hashing si


pe baza numarului rezultat se va stabili
locul perechii in Map.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cand folosim ArrayList si cand alegem LinkedList?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cand folosim ArrayList si cand alegem LinkedList?

Folosim ArrayList cand avem mai multe


cautari in colectie si LinkedList cand avem
adaugari si stergeri mai frecvente.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei Queue?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei Queue?


→ similar lui List, este o lista ordonata de
elemente, se pastreaza ordinea inserarii
→ este creata pentru ca elementele sa se
adauge la coada si sa se
stearga/proceseze de la capat
→ folosita atunci cand vrei sa procesezi
elemente in ordinea in care le-ai inserat
→ exista si o subinterfata a lui Queue
numita Deque care suporta procesarea de
la ambele capete
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei Queue?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei Queue?

Cele mai importante implementari ale


interfetei Queue sunt LinkedList,
PriorityQueue, ArrayDeque.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei Set?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei Set? → contine doar elemente unice, daca
adaugi acelasi element de doua ori, este
introdus doar o data
→ nu garanteaza ordinea elementelor, nu
pastreaza ordinea inserarii
→ exista o subinterfata a lui Set, numita
SortedSet in care elementele sunt sortate
(foloseste un o implementare a interfetei
Comparator, pentru a ordona elementele)
→ exista si o subinterfata a lui SortedSet
numita NavigableSet cu metode de
navigare prin colectie
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei Set?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei Set?

Cele mai importante implementari ale


interfetei Set sunt: HashSet,
LinkedHashSet, TreeSet.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce se intampla daca cheia unei perechi


cheie/valoare dintr-un Map se modifica?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce se intampla daca cheia unei perechi


cheie/valoare dintr-un HashMap se modifica?

Nu mai putem gasi valoarea in Map


folosind acea cheie, operatia
map.get(cheie); va returna null. De aceea
obiectele care vor fi folosite ca cheie in
HashMap trebuie sa fie imutabile.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetelor Set si List?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetelor Set si List?

Implementarile interfetei List au elementele


ordonate, permit elemente duplicat si
elementele sunt accesibile la un index.
Implementarile lui Set au elementele
neordonate, insa sunt unice, nu permit
duplicat.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care cele 4 interfete Map, Set, List, Queue, nu


este subinterfata a lui Collection?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care cele 4 interfete Map, Set, List, Queue, nu


este subinterfata a lui Collection?

Map
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cu ce implementare a Collections putem inlocui


un Array fara a schimba functionalitatea?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cu ce implementare a Collections putem inlocui


un Array fara a schimba functionalitatea?

Cu orice implementare a interfetei List.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei Map?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt particularitatile interfetei Map?

→ Map este o lista de cheie/valoare unde


cheia este unica
→ exista o subinterfata a lui Map, numita
SortedMap in care elementele sunt sortate
dupa cheie (foloseste Comparator)
→ exista si o subinterfata a lui SortedMap
numita NavigableMap cu metode de
navigare prin colectie
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum accesam o pereche cheie/valoare dintr-un


Map?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum accesam o pereche cheie/valoare dintr-un


Map?

Folosim cheia pentru a aduce valoarea:


T valoare = map.get(cheie);
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei Map?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care sunt cele mai importante implementari ale


interfetei Map?

Cele mai importante implementari ale


interfetei Map sunt: HashMap,
LinkedHashMap, TreeMap.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum este best practice sa fie obiectul care este


folosit ca si cheie intr-un map?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum este best practice sa fie obiectul care este


folosit ca si cheie intr-un map?

Imutabil.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cand vrem sa eliminam elemente duplicat dintr-o


structura de date, in ce structura de date le
putem adauga ca sa ramana doar elemente
unice?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cand vrem sa eliminam elemente duplicat dintr-o


structura de date, in ce structura de date le
putem adauga ca sa ramana doar elemente
unice?
Daca adaugam elementele intr-o structura
de date de tip Set vom elimina elementele
duplicat.
Exceptions
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exceptiile sunt evenimente sau probleme care au loc in timpul executiei unui program.
Cand apare o exceptie, fluxul normal al programului este alterat, iar programul se
termina anormal.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Superclasa acestor tipuri de evenimente se numeste Throwable care la randul ei


mosteneste clasa Object (clasa parinte a tuturor obiectelor din Java).
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

O exceptie poate avea loc din diferite motive:

- programul incearca citirea dintr-un fisier care nu exista;


- utilizatorul a transmis aplicatiei date invalide;
- - etc.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Throwable objects se impart in 3 categorii:

- Checked exceptions
- Unchecked exceptions
- Errors
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Checked exceptions
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

O exceptie checked este o exceptie notificata de compilator la compilare, de aceea se


mai numeste si exceptie la compile time.

Exceptiile checked nu pot fi ignorate de catre programator, ele trebuie tratate.


Java are o regula pentru aceste exceptii numita “handle or declare”.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

“Handle” sau tratatea exceptiei se face cu ajutorul blocului try-catch.


Codul din interiorul unui bloc try-catch se numeste cod protejat.

Sintaxa:
try {
//the try block = protected code
} catch(exception_type identifier) {
//exception handler
} finally {
//finally block
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Reguli de folosire try-catch:

- blocurile catch si finally sunt optionale, dar cel putin unul dintre ele
trebuie adaugat daca avem un bloc try

try {
//protected code
} //NU COMPILEAZA
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

- putem avea mai multe ramuri catch, insa pe fiecare ramura trebuie
sa declaram alt tip de exceptie

try {
//protected code
} catch(ExceptionTypeOne ex) {
//catch block for the first type of exception
} catch (ExceptionTypeTwo ex) {
//catch block for the second type of exception
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

- ordinea in care declaram blocurile catch este importanta, nu putem declara


mai intai o exceptie mai mare (mai ampla, parinte) si pe urmatorul bloc catch
sa tratam o exceptie mai mica (mai restrictiva, copil) deoarece compilatorul ne
atentioneaza ca avem “unreachable code”

try {
//protected code
} catch(ExceptionSuperclass ex) {

} catch (ExceptionSubclass ex) { // NU COMPILEAZA

}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

- putem prinde mai multe tipuri de exceptii intr-un singur bloc catch

try {
//protected code
} catch(ExceptionTypeOne | ExceptionTypeTwo ex) {
//catch block
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

- nu putem prinde aceeasi exceptie pe mai multe ramuri catch

try {
//protected code
} catch(ExceptionTypeOne | ExceptionTypeTwo ex) {
//catch block
} catch (ExceptionTypeTwo ex) { //NU COMPILEAZA

}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

- codul din blocul finally este executat indiferent daca codul protejat arunca
sau nu exceptie

try {
//protected code
} catch (Exception ex) {
//catch block
} finally {
//executed whether or not the protected code throws exception
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Dintre exceptiile checked amintim:

- FileNotFoundException: este aruncata programatic atunci cand codul refera


un fisier care nu exista
- IOException: este aruncata programatic atunci cand are loc o problema in
timpul citirii dintr-un fisier sau in timpul scrierii intr-un fisier.
- SQLException
- ClassNotFoundException
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Daca nu tratam cu un bloc try/catch exceptiile Checked aruncate de o metoda


trebuie sa le aruncam mai departe metodelor de mai jos din stack pentru ca
una din ele sa le trateze sau sa le arunce catre JVM.

Pentru a specifica ca nu am tratat exceptia si trebuie sa o trateze o alta


metoda trebuie sa adaugam la declararea metodei specificatorul throws si
numele Exceptiei.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

public class AnotherClass {


public void anotherProcess() throws FileNotFoundException {
//This code throws java.io.FileNotFoundException
FileReader fr = new FileReader("D:\\testout.txt");
}
}

public class OtherClass {


public void otherProcess() throws FileNotFoundException {
AnotherClass anotherClass = new AnotherClass();
anotherClass.anotherProcess();
}
}

public class Main {


public static void main(String[] args) {
OtherClass otherClass = new OtherClass();
try {
otherClass.otherProcess();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Unchecked exceptions
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

O exceptie unchecked este o exceptie ce are loc la momentul executiei


programului, de aceea se mai numeste si exceptie la runtime.

Exceptiile unchecked reprezinta buguri cum ar fi erori de logica si utilizarea


gresita a API-ului.

Pentru exceptiile unchecked nu se aplica regula “handle or declare”, ele fiind


ignorate la compile time.

Cu toate acestea programatorul poate proteja codul folosind constructia try-


catch.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exceptiile unchecked sunt apartin claselor care extind clasa RuntimeException.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exemple de exceptii unchecked

ArithmeticException - este aruncata de JVM atunci cand in cod se incearca impartirea la zero.

ClassCastException - este aruncata de JVM atunci cand se incearca cast-ul unei clase la o alta clasa,
conversia facandu-se la o subclasa fara insa ca referinta sa fie instanta a subclasei.

ArrayIndexOutOfBoundsException - este aruncata de JVM atunci cand se incearca accesarea unui


index care nu exista in array-ul respectiv.

IllegalArgumentsException – este o exceptie unchecked aruncata de programator pentru a indica


faptul ca o metoda a fost apelata cu un argument ilegal.

NullPointerException – este o exceptie unchecked aruncata de JVM atunci cand in cod exista o
referinta nula desi ar fi trebuit sa existe un obiect.

NumberFormatException – aruncata atunci cand se vrea conversia de la String la un tip numeric desi
stringul respectiv nu are formatul corespunzator.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Errors
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

A treia categorie este reprezentata de clasa Error care extinde clasa Throwable,
dar difera de exceptii prin faptul ca programatorul nu ar trebui sa le trateze sau
sa le declare.

Erorile reprezinta conditii anormale din care un program nu isi poate reveni.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exemple de erori din Java:

ExceptionInInitializerError,
IllegalAccessError,
InternalError,
OutOfMemoryError.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

StackOverflowError.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

public class ErrorExample {


public static void main(String[] args) {
boolean flag = true;
printHello(flag);
}

public static void printHello(boolean flag) {


while (flag) {
printHello(flag);
}
}
}

Uitam sa mai facem flag-ul false. Rezultatul rularii programului va fi:


Exception in thread "main" java.lang.StackOverflowError at
CompanyJava/ro.company.exceptions.erorr.ErrorExample.printHello(ErrorExample.java:11)
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exceptii Custom
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Programatorii pot defini propriile Exceptii care nu sunt in limbajul Java sau care
nu sunt incluse intr-o librarie externa.

Exceptiile custom sunt folosite pentru a fi aruncate atunci cand vrem sa trimitem
utilizatorilor un mesaj de eroare personalizat atunci cand in logica aplicatiei se
intampla un eveniment nedorit dar anticipat de programator.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exceptiile sunt de doua tipuri:


- checked (OurOwnException extends Exception)
- unchecked (AnotherCustomException extends RuntimeException)

Exceptiile checked trebuie tratate sau aruncate iar cele unchecked pot fi tratate
cu try/catch doar daca programatorul considera ca este necesar.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

In cele mai multe cazuri exceptiile definite de programatori sunt de tipul


Unchecked.

Sintaxa:

public class EmployeeAlreadyExistsException extends RuntimeException {



}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Pentru a arunca o exceptie, checked sau unchecked, definita de programator


sau existenta in limbaj folosim specificatorul throw:

private void verifyIfEmployeeAlreadyExists(Employee employee) {


for(Employee oldEmployee : DatabaseSimulation.EMPLOYEES){
if(oldEmployee.equals(employee)){
throw new EmployeeAlreadyExistsException("Angajatul exista deja in baza de date!");
}
}
}
Recapitulare
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce sunt exceptiile?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce sunt exceptiile?

Exceptiile sunt evenimente sau probleme


care au loc in timpul executiei unui
program.
Cand apare o exceptie, fluxul normal al
programului este alterat, iar programul se
termina anormal.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care este superclasa tuturor exceptiilor?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care este superclasa tuturor exceptiilor?

Throwable.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce superclasa extind exceptiile checked?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce superclasa extind exceptiile checked?

Exception.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce superclasa extind exceptiile unchecked?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce superclasa extind exceptiile unchecked?

RuntimeException.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce superclasa extinde Error?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce superclasa extinde Error?

Throwable
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum putem trata exceptiile?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum putem trata exceptiile?

Folosind blocuri de cod try/catch.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum se numeste blocul de cod care va fi


executat indiferent daca este aruncata o
exceptie sau nu?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum se numeste blocul de cod care va fi


executat indiferent daca este aruncata o
exceptie sau nu?

Finally (try/catch/finally)
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care dintre cele doua tipuri de exceptii trebuie


tratate cu try/catch sau aruncate cu throws
obligatoriu?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care dintre cele doua tipuri de exceptii trebuie


tratate cu try/catch sau aruncate cu throws
obligatoriu?

Checked (cele care extind Exception)


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exista blocuri de cod try fara catch sau finally?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exista blocuri de cod try fara catch sau finally?

Da, este obigatoriu sa avem cel putin un


catch sau finally. Dar putem aveam atat
catch cat si finally in acelasi timp.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Putem specifica pe ramura catch mai multe


exceptii?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Putem specifica pe ramura catch mai multe


exceptii?

Da, folosim operatorul pipe | pentru a


specifica mai multe tipuri de exceptii.

} catch(ExceptionTypeOne | ExceptionTypeTwo ex) {


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Daca avem mai multe blocuri catch. Care este


ordinea in care trebuie sa specificam exceptiile?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Daca avem mai multe blocuri catch. Care este


ordinea in care trebuie sa specificam exceptiile?

Trebuie sa le specificam in functie de


specificitatea lor. De la cea mai specifica la
cea mai generica.
SuperSuperException -> SuperException -> Exception
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Puteti da cateva exemple de exceptii Checked


prezente in limbaj?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Puteti da cateva exemple de exceptii Checked


prezente in limbaj?

FileNotFoundException, IOException,
SQLException, ClassNotFoundException
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Puteti da cateva exemple de exceptii


Unchecked prezente in limbaj?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Puteti da cateva exemple de exceptii


Unchecked prezente in limbaj?

ArithmeticException, ClassCastException,
ArrayIndexOutOfBoundsException
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care este cea mai intalnita exceptie din limbajul


Java?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Care este cea mai intalnita exceptie din limbajul


Java?

NullPointerException
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exemple de Error prezente in limbaj?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exemple de Error prezente in limbaj?

OutOfMemoryError, StackOverflowError
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum putem crea o exceptie checked?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum putem crea o exceptie checked?

Scriem o clasa care extinde Exception.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Dar o exceptie unchecked?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Dar o exceptie unchecked?

Scriem o clasa care extinde


RuntimeException
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum aruncam o exceptie?


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum aruncam o exceptie?

Folosim instructiunea

throw new ExceptionHere();


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum declaram ca o metoda arunca o exceptie


checked?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum declaram ca o metoda arunca o exceptie


checked?

Folosim la declararea sa specificatorul


throws urmat de denumirea exceptiei.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Daca o metoda declara ca arunca o exceptie


checked, mai trebuie sa trateze exceptia sau
trebuie sa o trateze metoda care o apeleaza?
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Daca o metoda declara ca arunca o exceptie


checked, mai trebuie sa trateze exceptia sau o
trebuie sa o trateze metoda care o apeleaza?

Metoda care o apeleaza trebuie sa trateze


exceptia.
Working with Files
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Input/Output streams (intrare/iesire sau citire/scriere)

Java efectueaza operatiunile de intrare/iesire


(denumite I/O de la Input/Output)
prin fluxuri (streams).

Un stream este legat de un strat fizic de catre sistemul I/O din Java pentru a efectua
operatiuni de intrare si de iesire. In general, un stream inseamna un flux continuu de date.

Un stream I/O reprezinta o sursa de intrare sau o destinatie de iesire.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

In functie de directia transferului de date, stream-urile pot fi:

- de iesire: care transfera datele dintr-o aplicatie catre exterior.


- de intrare: care transfera datele din exterior catre apliactie.
- bidirectionale: care transmit datele in ambele directii.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Un stream poate reprezenta mai multe tipuri de surse si destinatii:


fisiere pe disc, dispozitive, alte programe, memoria RAM, consola, sockets.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este un socket?

Un socket este un punct final al unei legaturi de comunicatie bidirectionala intre doua
programe care ruleaza in retea.

Clasele socket sunt utilizate pentru a reprezenta conexiunea dintre un program client si un
program server.

Packetul java.net ofera doua clase - Socket si ServerSocket - care implementeaza partea
de client a conexiunii, respectiv partea de server a conexiunii.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exista doua tipuri de streamuri:

- Byte stream (flux de octeti): ofera un mijloc convenabil de gestionare a intrarii si iesirii de
octeti.

- Character stream (flux de caractere): ofera un mijloc convenabil de gestionare a intrarii si


iesirii de caractere. Fluxul de caractere utilizeaza Unicode si, prin urmare, poate fi
internationalizat.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Byte Stream (flux de octeti)

Fluxul de octeti este definit prin utilizarea a doua clase abstracte in partea de sus a
ierarhiei, acestea fiind InputStream si OutputStream.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Character Stream

Fluxul de caractere este, de asemenea, definit prin utilizarea a doua clase abstracte in
partea de sus a ierarhiei, acestea fiind Reader si Writer.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Clasa File

Inainte de a ne focusa pe aceste clase in detaliu, trebuie sa aducem in discutie clasa File
care face parte din pachetul java.io si care ne ajuta sa lucram cu fisierele si folderele de pe
disc.

Clasa File nu se ocupa cu scrierea si citirea din/in fisiere, ci contine informatii despre
fisierele si structura directoarelor de pe disc.

Atunci cand cream un obiect al clasei File, nu inseamna ca am creat un fisier pe disc.

Clasa File contine mai multe metode pentru crearea, stergerea si redenumirea fisierelor,
crearea de directoare noi, listarea continutului unui director si determinarea mai multor
atribute comune ale fisierelor si directoarelor.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Clasa File este o reprezentare abstracta a cailor de acces ale fisierului sau folderului.
Instanta clasei File este imutabila; adica, odata creata, calea abstracta reprezentata de un
obiect File nu se va schimba niciodata.

Pentru a folosi clasa File, trebuie sa o importam:


import java.io.File;

Pentru a vedea ce constructori si metode sunt disponibile in clasa File, putem consulta
documentatia oficiala: https://docs.oracle.com/javase/8/docs/api/java/io/File.html
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Byte Streams – clasele FileInputStream si FileOutputStream

FileInputStream si FileOutputStream sunt doua clase folosite pentru a citi si scrie informatie
octet cu octet. Sunt folosite in special pentru fisiere care contin octeti, precum imaginile.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

ByteArrayInputStream si ByteArrayOutputStream

ByteArrayInputStream este o clasa cu ajutorul careia putem citi un sir de octeti ca flux de
intrare, dupa cum sugereaza si numele.
ByteArrayOutputStream este o clasa cu ajutorul careia putem scrie un sir de octeti ca flux
de iesire.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

ObjectInputStream si ObjectOutputStream

Clasa ObjectOutputStream din pachetul java.io poate fi utilizata pentru a scrie obiecte care
pot fi citite de clasa ObjectInputStream.

Clasa ObjectOutputStream extinde OutputStream.

ObjectOutputStream codifica obiecte Java folosind numele clasei si starea obiectului,


generand fluxuri de date corespunzatoare. Acest proces este cunoscut sub numele de
serializare.

Aceste fluxuri convertite pot fi stocate in fisiere sau tranferate intre retele de calculatoare.
ObjectOutputStream/ObjectInputStream pot lucra doar cu clase care implementeaza
interfata Serializable.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Interfata Serializable

Interfata Serializable face parte din pachetul java.io si este o interfata marker, in sensul ca
marcheaza clasele care o implementeaza ca fiind clase (obiecte) ce pot fi
serializate/deserializate.

Serializarea (scrierea) obiectelor in Java se face cu ObjectOutputStream, iar deserializarea


(citirea) se face cu ObjectInputStream.

Pentru ca Serializable este o interfata marker inseamna ca nu are membri, nu contine nici o
metoda, prin urmare clasa care implementeaza interfata Serializable nu trebuie sa
implementeze metode specifice.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

ObjectInputStream

Clasa ObjectInputStream a pachetului java.io poate fi utilizata pentru a citi obiecte care au
fost scrise anterior de ObjectOutputStream.

Clasa ObjectInputStream extinde InputStream.

Clasa ObjectOutputStream mai intai converteste obiectele ce pot fi serializate in fluxuri de


date, le stocheaza in fisiere sau le transmite in retea, apoi aceste fluxuri de date pot fi citite
de catre ObjectInputStream si convertite inapoi in obiecte Java. Acest proces este cunoscut
ca deserializare.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

BufferedInputStream si BufferedOutputStream

BufferedInputStream si BufferedOutputStream utilizeaza un array intern de octeti, cunoscut


si sub numele de buffer, pentru a stoca date in timpul citirii, respectiv scrierii. Buffered
streams sunt de obicei mai eficiente decat non-buffered streams.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Character streams

Platforma Java stocheaza valorile caracterelor folosind conventiile Unicode. Fluxul de


caractere I/O traduce automat acest format intern in si din setul de caractere local.

Pentru majoritatea aplicatiilor, operatiile de I/O realizate cu ajutorul fluxurilor de caractere,


nu sunt mai complicate decat cele realizate cu fluxurile de octeti. Intrarea si iesirea realizate
cu clasele specifice fluxurilor de caractere, se traduc automat in si din setul de caractere
locale. Un program care foloseste fluxuri de caractere in locul fluxurilor de octeti se
adapteaza automat la setul de caractere locale.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Platforma Java stocheaza valorile caracterelor folosind conventiile Unicode. Fluxul de


caractere I/O traduce automat acest format intern in si din setul de caractere local.

Pentru majoritatea aplicatiilor, operatiile de I/O realizate cu ajutorul fluxurilor de caractere,


nu sunt mai complicate decat cele realizate cu fluxurile de octeti. Intrarea si iesirea realizate
cu clasele specifice fluxurilor de caractere, se traduc automat in si din setul de caractere
locale. Un program care foloseste fluxuri de caractere in locul fluxurilor de octeti se
adapteaza automat la setul de caractere locale.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Principalul avantaj al fluxurilor de caractere este ca faciliteaza scrierea de programe care


nu depind de o anumita encodare (codificare a caracterelor) => sunt usor de
internationalizat.

Java stocheaza sirurile de caractere in Unicode care este un standard international de


codificare a caracterelor. Cu ajutorul Unicode pot fi reprezentate majoritatea caracterelor
din limbile scrise.
Fisierele text tipice care pot fi citite de catre utilizatori, pot folosi codificari ca nu sunt
neaparat legate de Unicode, exista multe alte tipuri de codificari de caractere.
La finalul acestei pagini exista o lista cu cele mai comune codificari de caractere si
subseturile lor: https://en.wikipedia.org/wiki/Character_encoding#:~:text=Common
%20examples%20of%20character%20encoding,Interchange%20(ASCII)%20and
%20Unicode.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Fluxurile de caractere ascund complexitatea gestionarii acestor codificari oferind doua


clase care servesc drept punte intre fluxurile de octeti si fluxurile de caractere.

Un alt avantaj al fluxurilor de caractere este ca au potentialul de a fi mult mai eficiente decat
fluxurile de octeti.
Maven
(short introduction)
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Maven este o unealta folosita pentru a crea un proiect si pentru a-i manageria dependintele.
Este un build tool, compileaza codul folosind compilatorul, executa unit tests etc.
Acesta standardizeaza si structura folderelor intr-o aplicatie.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Aplicatiile Java pot folosi diferite librarii open source, gratuite.


Acestea introduc functionalitati noi aplicatiei pe care o dezvoltam.

Unul dintre scopurile Maven este sa managerieze aceste dependinte.


Acesta le descarca de pe diferite servere si le adauga proiectului nostru.
Fisierul de configurare Maven este numit pom.xml (Project Object Model).
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Pe langa managementul dependintelor, Maven, poate crea si o


arhiva a aplicatiei noastre de tip JAR (Java Archive), WAR (Web
Application Archive), etc. care poate fi distribuita.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Pentru a crea o aplicatie care foloseste Maven cu Intellij urmam urmatorii pasi:
File -> New -> Project -> Selectam Maven - > Dam un nume proiectului si locatia pe
HDD
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Structura proiectului generat este similara cu cea din exemplul urmator:

Folderul main/java va contine fisierele .java cu cod organizat in pachete si main/resources


fisiere de configurare, fisiere statice precum .html .js, .xml, etc.
Folderul test/java va avea aceeasi structura a pachetelor precum cea a folderului main/java
insa clasele din acest folder vor contine teste pentru clasele din pachetul main.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Pentru a adauga dependente proiectului nostru accesam fisierul pom.xml si adugam


dependente intre tag-urile:

<dependencies>

</dependencies>
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

De unde putem lua dependente Maven?


Cel mai cunoscut repository cu
dependente este Maven Central si
este accesibil la
https://mvnrepository.com/repos/central

Fiecare companie poate avea un repository intern cu dependinte specifice acelei companii,
pe care le putem accesa si le putem adauga proiectului nostru.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

In acest repository putem cauta dependente precum, JUnit (JUnit Jupiter Engine), folosita
pentru a crea teste unitare codului nostru.

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>

Dupa adaugarea dependintei in pom.xml aceasta va fi descarcata si clasele ei vor fi


disponibile in proiectul nostru.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Aceleasi dependinte adaugate folosind Maven pot fi adaugate si unui proiect clasic Java,
precum cele pe care le-am vazut pana acum.

Insa folosind Maven, acesta le descarca si le adauga pentru noi in proiect.

Exista si tooluri mai noi si mai performante decat Maven, precum Gradle, insa Maven inca
este solutia cea mai folosita in proiecte.
Unit tests
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Testele unitare sunt teste scrise de programatori si verifica


daca o unitate de cod se comporta asa cum a fost proiectata.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Aceste teste pot fi executate de fiecare data cand dorim sa ne


asiguram ca modificarile facute in cod nu afecteaza alte zone testate.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

O clasa de test este o clasa Java in care avem metode adnotate cu @Test.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Sintaxa:
class TestClass {
@Test
public void should_returnResult_when_parametersArePassed() {
MyClass myClass = new MyClass();
assertEquals(7, myClass.sum(2,5))
};
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Printr-o unitate de cod intelegem testarea metodelor, acestea fiind cea mai
mica unitate de cod care poate fi testata.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Testarea unitara a codului este importanta pentru ca putem testa toate


conditiile unei metode si astfel vom stii ca, codul nostru se comporta asa
cum am planuit atunci cand l-am scris.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Testele ne ofera siguranta ca o data modificata o parte a aplicatiei nu am


afectat alta zona a sa.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

In programare pe masura ce aplicatiile devin din ce in ce mai mari, fara


teste unitare va fi foarte dificil sa modificam, sa adaugam sau sa
imbunatatim functionalitati existente.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Testele unitare sunt grupate in pachete si clase similar codului de productie.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

JUnit este cel mai cunoscut framework de testare unitara pentru


aplicatii Java.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cand scriem un test verificam daca o metoda returneaza ceea ce ne asteptam sa


returneze.

Metodele statice de tip assert din clasa Assertions se folosesc pentru a verifica daca
rezultatul returnat de o metoda este ceea ce asteptam.

Fara o metoda de assert testele noastre nu au niciun scop real.

Exemplu de metoda de assert:


assertEquals(7, myClass.sum(2,5));

Pe langa metoda assertEquals() care este supraincarcata de multe ori cu diferite tipuri de
date, in clasa Assertions gasim si alte metode de assert: assertArrayEquals(..),
assertNotEquals(...), assertTrue(...), assertFalse(...), assertNull(...), assertNotNull(...)
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Reguli de denumire a testelor

Sunt mai multe reguli de denumire a testelor, printre cele mai populare sunt formele:

Should_ExpectedBehavior_When_StateUnderTest:
Should_ThrowException_When_AgeLessThan18,
Should_FailToWithdrawMoney_ForInvalidAccount,
Should_FailToAdmit_IfMandatoryFieldsAreMissing

test[Feature being tested]:


testIsNotAnAdultIfAgeLessThan18,
testFailToWithdrawMoneyIfAccountIsInvalid,
testStudentIsNotAdmittedIfMandatoryFieldsAreMissing
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum testam unitar metode care apeleaza alte


metode?

Pentru a testa unitar o metoda, trebuie sa o izolam de


restul metodelor pe care ea le apeleaza.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este Mokito?

Mockito este un framework de mocking, cu ajutorul


caruia poti inlocui obiecte concrete cu alte obiecte
virtuale (mocks) si poti simula raspunsuri venite de la
metodele acestor obiecte.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum putem izola o metoda pentru a o putea testa unitar?

Pentru a putea izola o metoda care apeleaza alte metode


putem folosi un framework de mock-ing precum Mockito.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

In exemplul de mai jos, metoda saveOrUpdate() apeleaza la randul sau 2 metode,


employeeRepository.update(employee); si employeeRepository.save(employee);
pe care nu vrem sa le testam. Pentru izolarea metodei saveOrUpdate() trebuie sa inlocuim implementarea
employeeRepository cu o clasa fictiva si apoi sa inlocuim rezultatul returnat de metodele save si update.

Metoda ce trebuie testata: saveOrUpdate() class EmployeeServiceImplTest {


//Mock the repository
class EmployeeServiceImpl implements EmployeeService { EmployeeRepository employeeRepository = Mockito.mock(EmployeeRepositoryImpl.class);

private EmployeeRepository employeeRepository; //Create the class under test


EmployeeService employeeService = new EmployeeServiceImpl(employeeRepository);
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
@Test
} public void should_saveEmployee_when_newEmployeeIsPassed(){
//create a new employee
@Override Address address = new Address("Str1", "85b");
public void saveOrUpdate(Employee employee) { Employee employee = new Employee(1, "John Doe", 10000, address);
//check if employee is already in the database
Employee dbEmployee = employeeRepository.getById(employee.getId());
//mock get employee
if(dbEmployee != null){
when(employeeRepository.getById(1)).thenReturn(null);
//if it exists, update
employeeRepository.update(employee);
} else { //save employee
//else save it employeeService.saveOrUpdate(employee);
employeeRepository.save(employee);
} verify(employeeRepository, times(1)).save(employee);
} verify(employeeRepository, times(0)).update(employee);
}
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum testam metode private?

Putem testa metode private prin intermediul metodelor publice care le apeleaza.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum testam metode care nu returneaza nimic?

Ca sa testam metode care nu returneaza nimic putem fie sa testam daca au


modificat starea unui obiect sau putem verifica daca in interiorul lor s-a apelat o
anumita metoda cu un anumit parametru asteptat.

@Test
public void should_deleteAllEmployees(){
//create an employee, save him
Address address = new Address("Str1", "85b");
Employee employee = new Employee(1, "John Doe", 10000, address);
employeeRepository.save(employee);

//create an employee, save him


Employee employee2 = new Employee(2, "Mary Doe", 12000, address);
employeeRepository.save(employee2);

//delete all employees


employeeRepository.deleteAll();

assertEquals(0, employeeRepository.getAll().size());
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este code coverage?

Code coverage reprezinta procentul de cod de productie acoperit de teste unitare. Putem rula testele
unitare dintr-o aplicatie si putem vedea ce zone de cod au fost testate si care nu au fost testate.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce alte tipuri de testare mai exista?

Mai exista si testare de integrare, care testeaza mai multe componente ale
aplicatiei in acelasi timp dar si testarea functionala sau e2e care testeaza
aplicatia simuland interactiunea unui utilizator cu interfata aplicatiei.
Multithreading
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este un procesor?
Din ce este format un procesor?
Ce este un Thread? Ce este Hyperthreading?
Procesorul este componenta care executa
instructiunile transmise de programe. Un
procesor este format din unul sau mai multe
core-uri, fiecare core are un thread fizic dar cu
tehnologia Hyperthreading acesta poate avea
doua thread-uri logice cu ajutorul carora poate
procesa informatia in paralel pana o transmite
threadului fizic pentru a continua procesarea.
Fiecare aplicatie are un proces, fiecare proces
poate fi format din unul sau mai multe
threaduri si in general este bine in programe
sa ai atatea thread-uri cate core-uri/threaduri
ai, bineinteles, daca ai ce sa faci pe ele, pentru
ca in unele cazuri procesul de imparire a
taskului pe threaduri, procesarea in paralel si In cazul procesoarelor cu Hyperthreading daca cele doua threaduri logice
termina procesarea in acelasi timp unul dintre ele trebuie sa astepte pe
apoi de unire a rezultatelor este mai ineficient
celalalt sa dea informatia mai departe threadului fizic, deci va fi un fel de
decat procesarea directa pe un singur thread. ambuteiaj. Cresterea in performanta este doar atunci cand unul dintre
Exista mai multe tipuri de procesoare: Single threaduri termina mai repede decat celalalt.
Core, Multi Core si Multi Core cu Diferenta de performanta intre un procesor cu Hyperthreading si altul fara
Hyperthreading. este de aproximativ 25%.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Platforma Java a fost proiectata astfel incat sa suporte programarea concurenta.

Concurenta (Concomitenta) reprezinta capacitatea sistemelor de a executa mai


multe operatii simultan, eventual interactionand unele cu altele.

In programarea concurenta, exista doua unitati de baza: procesul si firul de executie.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Un proces reprezinta un set de activitati care interactioneaza pentru a produce un


rezultat, este un program in executie.

De multe ori procesele sunt considerate sinonime cu programele/aplicatiile, insa o


aplicatie poate avea mai multe procese.

Un proces are un mediu de executie autonom. Fiecare proces are propriul spatiu de
memorie si are in general un set de resurse de baza in timpul rularii.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Firele de executie mai sunt numite si procese lightweight.

Un proces are cel putin un fir de executie. In cazul in care un proces are
mai multe fire de executie (threads) acestea pot sa proceseze in paralel.

Firele de executie impartasesc resursele din cadrul unui proces.

Acest lucru sporeste performanta, dar poate duce si la diverse probleme.

Concomitenta promite executarea anumitor task-uri mai rapid, acestea


fiind impartite in subtask-uri, iar subtask-urile executandu-se in paralel.
Performanta posibila teoretica obtinuta se calculeaza cu Legea Amdahl.

Daca taskurile nu sunt mari, de exemplu procesarea unui fisier mare,


concomitenta poate incetini procesul deoarece impartirea taskurilor in
subdiviziuni de lucru dureaza.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Posibile probleme ale concurentei sunt:

Vizibilitatea (daca thread-ul A citeste informatii share-uite de thread B,


apoi thread B modifica informatiile, atunci thread A nu va sti de aceasta
modificare)

Accesul (se intampla atunci cand mai multe thread-uri vor sa acceseze si
sa modifice informatiile in acelasi timp). Aceste probleme cauzeaza
deadlock-uri (programul nu mai reactioneaza) sau programul furnizeaza
informatii incorecte.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Fiecare fir de executie este asociat cu o instanta a clasei Thread.

Exista doua strategii de baza de utilizare a firelor de executie in vederea


crearii unei aplicatii concurente.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Prima strategie se refera la controlarea in mod direct a crearii si a


gestionarii firelor de executie.

De fiecare data cand aplicatia trebuie sa initieze o activitate asincrona,


vom instantia clasa Thread.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

A doua strategie se refera la abstractizarea gestionarii firelor de executie,


trasmitand sarcinile aplicatiei unui executor.

Executorii definesc un API de nivel inalt pentru lansarea si gestionarea


firelor. Implementarile executorilor furnizate de java.util.concurrent
asigura gestionarea pool-ului de thread-uri adecvat pentru aplicatii pe
scara larga.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exista doua modalitati de a crea un fir de executie utilizand prima strategie.

1. Prin extinderea clasei Thread din pachetul java.lang si suprascrierea metodei run()
din clasa Thread.

public class MyThread extends Thread {


public void run() {
System.out.println("Thread started...");
}
}

Ca sa pornim firul de executie:


public class Main {
public static void main(String[] args) {
(new MyThread()) } .start();

}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

2. Prin implementarea interfetei Runnable care este o interfata functionala si care


contine o metoda abstracta run(). Clasa Thread implementeaza la randul ei aceasta
interfata.

public class MyThread implements Runnable {


public void run() {
System.out.println("Thread started...");
}
}

Ca sa pornim firul de executie:


public class Main {
public static void main(String[] args) {
(new Thread(new MyThread())).start();
}
}
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

In ambele situatii, pentru a porni thread-ul, apelam metoda start() existenta in clasa Thread.
Este de preferat sa folosim cea de-a doua varianta (implementarea interfetei Runnable)
deoarece obiectul nostru Runnable poate fi clasa-copil a oricarei alte clase, nu neaparat a
clasei Thread. Asadar folosind aceasta optiune avem mai multa flexibilitate.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ciclul de viata al firelor de executie


1. New – orice fir de executie isi incepe ciclul de viata in starea new si ramane in aceasta
stare pana cand aplicatia porneste firul.
2. Runnable – dupa ce aplicatia a pornit firul, acesta trece in starea runnable si se
considera ca firul este in executie.
3. Waiting – un fir poate fi in asteptare pana ce alt fir isi termina executia. Atunci cand firul in
cauza se termina de executat, firul care este in asteptare trece in executie, adica devine
runnable.
4. Timed Waiting – un fir poate trece in starea de asteptare pentru un anumita perioada de
timp, ca apoi la finalul scurgerii timpului sa treaca in executie.
5. Terminated (Dead) – la finalul executiei unui fir, acesta trece in starea terminated,
insemnand ca a terminat de executat task-ul.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Metode disponibile in clasa Thread

Clasa Thread defineste o serie de metode utile pentru gestionarea firelor de executie.

API-ul complet poate fi consultat aici:


https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Metoda start porneste executarea firului, JVM apeleaza metoda run() al firului de executie.

De asemenea cu ajutorul metodei sleep putem pune pe pauza executia firului. La apelul
acestei metode, firul isi va suspenda executia pentru o anumita perioada de timp.
Exista doua variante ale metodei sleep. Una care primeste ca parametru un numar de
milisecunde reprezentand numarul de milisecunde pentru care firul sa-si intrerupa executia.
A doua varianta asteapta doua argumente: numarul de milisecunde si numarul de
nanosecunde care reprezinta perioada (nr. milisecunde + nr. nanosecunde) pentru care firul
sa-si suspende executia.

Un fir de executie poate fi intrerupt cu ajutorul metodei interrupt. Prin intrerupere se intelege
in general ca firul isi termina executia.

Metoda join permite unui fir sa astepte alt fir sa-si termine executia.
Metoda setName ne permite sa dam un anumit nume firului de executie.
Cu ajutorul metodei setPriority putem specifica o prioritate (MIN_PRIORITY = 1 si
MAX_PRIORITY = 10). By default, fiecare fir are prioritatea NORM_PRIORITY = 5.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Asincronicitatea

Intr-un model de programare sincrona, task-urile se executa pe rand.

Cand este apelata o functie care efectueaza o actiune de lunga durata, aceasta intoarce
rezultatul cand actiunea s-a incheiat, iar in timpul acesta programul asteapta dupa rezultat.

De abia cand se primeste rezultatul, se trece mai departe la urmatorul task.

Un model asincron permite ca mai multe task-uri sa se intample in acelasi timp.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Lucrul cu mai multe fire de executie introduce un comportament asincron.


Dezavantajul ar fi ca pot aparea inconsistente. De exemplu, daca un thread citeste niste
informatii (dintr-un fisier, din baza de date, din alta clasa) si alt thread modifica informatiile
respective, acest lucru se poate intampla in acelasi timp, fapt ce duce la date inconsistente.

Cand doua sau mai multe fire de executie trebuie sa acceseze aceleasi resurse este nevoie
sa facem astfel incat firele de executie sa acceseze resursele respective pe rand pentru a
elimina inconsistentele. Acest lucru este posibil cu ajutorul sincronizarii.

Pentru a crea zone mutex (sincronizate) putem folosi specificatorul syncronized insa nu
este singurul mod prin care putem realiza sincronizarea, putem folosi si Semaphores sau
Lock API.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este Mutual Exclusion (Mutex)?

Mutual Exclusion este modul prin care protejam blocuri de cod sa nu poata fi accesate de
doua sau mai multe threaduri in acelasi timp. Este un mod de a proteja un “critical section”.

In Java specificatorul syncronized, Lock API sau Semaphores sunt folosite pentru a proteja
un “critical section”.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Semaphores sunt un alt mod prin care putem realiza sincronizarea unei zone a codului
nostru.

Clasa Semaphore din Java controleaza accesul firelor de executie la o resursa partajata
prin intermediul unui contor.
Daca contorul este mai mare ca zero, atunci accesul la resursa este permis.
Daca contorul ajunge la zero, atunci accesul este refuzat.

Exemple:
https://www.baeldung.com/java-semaphore
https://www.geeksforgeeks.org/semaphore-in-java/
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce inseamna Thread-Safe?

Un obiect thread safe este un obiect ce poate fi accesat de mai multe threaduri fara sa
apara probleme/anomalii.

Unele obiecte thread safe au accesul la resurse este limitat la un thread per moment, ceea
ce insemna ca threadurile trebuie sa le acceseze pe rand in serie, unu cate unu.

Alte obiecte thread safe sunt cele imutabile, deci threadurile pot doar sa citeasca informatia
fara sa o modifice. Folosind obiecte imutabile, 2 sau mai multe threaduri pot accesa
obiectul in acelasi timp fara a avea anomalii de citire sau scriere.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este un Deadlock?

Cand doua threaduri se asteapta unul pe


celalalt la nesfarsit atunci se considera ca avem
deadlock. Threadul 1 este oprit pana termina
Threadul 2, Threadul 2 este oprit pana termina
Threadul 1.

Exemplu: T1 apeleaza metoda syncronized1 |


T2 vrea sa apeleze si el syncronized1 | T2 a
apelat si el o metoda syncronized2 | T1 vrea sa
apeleze si el syncronized2
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Cum poate fi evitat un Deadlock?

Deadlocks pot fi evitate/rezolvate prin mai multe


moduri:
→ evitarea apelarii zonelor mutex (aka
locked/mutex) din doua threaduri diferite
→ evitarea lockurilor circulare; toate threadurile
trebuie sa acceseze zonele mutex, in aceeasi
ordine, deci sa obtina lock-urile in aceeasi
ordine
→ reducerea numarului de mutex-uri, prin
unirea lor
etc.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Executors

ExecutorService este o interfata aparuta in Java 5 cu care poti executa taskuri asincron.
Folosind un ExecutorService poti crea si manageria un thread sau un pool de threaduri si ai
mai mult control asupra lor, in sensul ca stii cate sunt executate in acelasi timp sau la ce
interval de timp se vor executa.

Folosind ExecutorService este unicul mod prin care poti face un thread sa returneze ceva.
Folosesti obiecte care implementeaza Callable in loc de Runnable pentru a putea returna
rezultatul acelui thread intr-un obiect generic de tip Future. Future expune metode pentru a
monitoriza task-ul, poate verifica statusul si poate returna rezultatul.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

→ un ExecutorService cu un thread –
ExecutorService ex = Executors.newSingleThreadExecutor();

→ un ExecutorService cu un pool de threaduri cu numar fix de threaduri ce sunt executate simultan


ExecutorService ex = Executors.newFixedThreadPool(10);

→ un ExecutorService cu un pool de threaduri care pot fi executate periodic sau cu intarziere


ExecutorService ex = Executors.newScheduleThreadPool(10);
VCS
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este Version Control?

Este un sistem care monitorizeaza schimbarile documentelor, programelor etc. De obicei


fiecare schimbare se numeste versiune. De fiecare data cand se face o schimbare
sistemele Version Control fac un “snapshot” al proiectului si il salveaza astfel incat daca
exista o problema sa putem reveni la versiunea anterioara.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Motivele folosirii ar fi:


– posibilitatea de a reveni la o versiune anterioara;
– posibilitatea de a unifica codul mai multor dezvoltatori care lucreaza pe acelasi proiect;
– posibilitatea de a vedea ce, cand si cine a modificat proiectul;
– vei avea mereu un backup al proiectului pe serverul VCS
– vei avea acces remote la cod
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Exemple de VCS:

Git (distributed VC, dezvoltatorii au o copie locala a repository);


SVN (centralized VC, dezvoltatorii nu au o copie a repository locala, toti lucreaza direct pe repository central),
Mercurial (distributed VC, dezvoltatorii au o copie locala a repository),
CVS (centralized VC, dezvoltatorii nu au o copie a repository locala, toti lucreaza direct pe repository central).
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Git != GitHub

Git este o tehnologie de versionare, lansata de creatorul Linux, Linus Torvalds


GitHub este un provider (host) Git.
Exista si alte platforme care ofera servere Git, precum Bitbucket, Gitlab etc.

Companiile de obicei isi instaleaza apropriile servere de versionare, Git, SVN, private si nu
se bazeaza pe servere publice precum GitHub.

Invatam Git pentru a putea lucra cu toti providerii, precum GitHub, BitBucket, servere
private, etc.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Ce este si cum se foloseste Git?

Este un sistem Version Control distribuit, adica fiecare dezvoltator


are pe sistemul sau o copie a repository-ului.
In Git, repository-urile sunt de doua tipuri, local (este un folder .git
in proiect si numai utilizatorul acelui sistem il poate utiliza) si central
(folderul .git este remote si este folosit de intreaga echipa).
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

STARILE FISIERELOR

In Git fișierele pot fi în următoarele stadii:


– untracked (fișiere noi, care nu au fost niciodată commited in repository, nici macar staged)
– unmodified
– modified
– staged (a fost modificat și adăugat în lista de fișiere ce vor fi commited in repository)
(după commit fișierele trec în stare unmodified) (fișierele unmodified pot fi trecute și in
untracked) (doar fișierele staged for fi commited când aplicam comanda: git commit)
Putem vedea statusul fișierelor cu: git status

Pentru a trece fișierele untracked sau modified in stare staged folosim: git add -all

Comanda: git commit va commita doar fișierele staged


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Comenzi GIT (CMD LINE)


1.Pentru a initailiza un repository intr-un proiect local folosim: git init
2.Daca proiectul este deja remote intr-un server Git folosim pentru a-l downloada: git clone
<link>
3.Daca proiectul a fost initializat local (pasul1) pentru a-l lega de un repository nou existent
remote folosim:git add –all apoi git commit -m „first commit” apoi git remote add origin <link-
catre-repo> apoi git push -u origin master
4.Pentru a prelua apoi fiserele modificate remote folosesti: git pull sau git pull –rebase
5.Comanda git status pentru a vedea ce modificari au fost facute la repository local
6.Pentru a pune fisierele modificate in starea stage apoi in reporsitory local si apoi in cel
remote, folosesti git add . (pentru a adauga fisierele modificate in stage) apoi git commit –m
“mesaj” (pentru a adauga fisierele modificate in repo local) si apoi git push origin
branch_name_here (pentru a actualiza repository remote), numai dupa git push fisierele vor
ajunge in reporitory remote
7.Comanda git log, pentru a vedea history
8.Comanda git fetch va prelua history si noile branchuri de pe remote fara a downloada
continutul branch-urilor
9.Comanda git checkout branch_name, va schimba de pe un branch pe altul
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Learn more:
https://www.youtube.com/watch?v=8JJ101D3knE
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

→ Interfetele pot avea metode default cu implementare si metode statice cu implementare;


→ Referinte la o metoda User::isRealUser;
→ Clasa Optional;
→ Interfete functionale,
→ Expresii lambda;
→ Stream-uri,
→ String.join() function
Lambda Expressions & Functional
Interfaces
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Expresiile lambda fac parte din programarea functionala si sunt


un fel de metode anonime, au parametrii si corp dar nu au nume.

Sunt implementari ale metodei abstracte unice declarate intr-o


interfata functionala. Inlocuiesc clasele anonime.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

O interfata functionala este o interfata adnotata optional cu


@FunctionalInterface ce are o singura metoda abstracta.

Adnotarea @FunctionalInterface ne asigura ca interfata nu are


decat o singura metoda abstracta.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

JDK 8+ vine in pachetul java.util.function cu multe interfete


functionale deja disponibile pentru noi sa le implementam
folosind expresii lambda.
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
}

@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}

@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}

Putem scrie si propriile interfete functionale.


Streams
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Colectiile sunt grupuri de obiecte tratate ca o entitate.


Streamurile sunt folosite pentru a procesa aceste colectii.

A nu se confunda cu Streamurile de citire si scriere.


Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Un stream este secventa de obiecte de la o sursa care suporta operatii agregate


folosit pentru a transforma date. Este o structura abstracta, nu poate fi instantiata.

In Streams nu se modifica starea (state) la fiecare pas deci pot fi folosite cu


success in aplicatii multithread.

Pe streamurile generate putem aplica operatii n intermediare si doar o singura


operatie finala.
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Metode de generare a Streamurilor


.stream()
.parallelStream()

Exemplu:
List<Integer> list = Arrays.asList(1, 4, 6, 2, 7);
list.stream() //operatie de generare
.filter(i -> i > 3); // operatie intermediara , returneaza un stream modificat
.map(i -> i+3); //operatie intermediara, returneaza un stream modificat
.forEach(System.out::println); //operatie finala
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Metode intermediare

Operatiile intermediare primesc un stream si rezulta alt stream.


.map() – mapeaza o valoare in alta valoare
.flatmap()
.filter() – elimina elementele care nu trec conditia
.sorted() – sorteaza elementele din stream
.limit() – limiteaza nr de elemente din stream
.distinct() – elimina elementele duplicat din stream
.peek()
.skip()
Collections-Exceptions-Working with files-Multithreading-Unit tests-VCS

Metode terminale

Operatiile terminale consuma un stream si returneaza un rezultat


.reduce(inital_value, accumulator)
.collect();
.forEach(); – iterate each element
.forEachOrdered();
.toArray();
.min();
.max();
.count();
.anyMatch();
.allMatch();
.noneMatch();
.findFirst();
.findAny();
Subiecte de invatat pe viitor:
Spring
Design patterns
Principiile SOLID
Structuri de date
Algoritmi de sortare, cautare

S-ar putea să vă placă și