Sunteți pe pagina 1din 44

Programarea Java

1. Istoria succintă a limbajului de programare Java, avantajele limbajului de programare


Java
Java este un limbaj de programare orientat pe obiecte asemănător limbajului C++. Inceptul
limbajului Java este in toamna anului 1991, cand firma Sun Microsystems a finantat un proiect cu
numele Green condus de James Gosling. Tehnologia propusa a avut un impact remarcabil asupra
intregii comunitati a dezvoltatorilor de software, impunandu-se prin calitati deosebite cum ar fi
simplitate, robustete si nu in ultimul rand portabilitate.
Dupa patru ani de lucru, echipa Green finalizeaza specificatiile limbajului Java, astfel ca in anul
1995 firma Sun Microsystems vinde licenta firmelor IBM, Microsoft, Silicon Graphic, Adope si
Netscape.
Incepand cu anul 1998, cand a aparut versiunea 2 a limbajului (Java 2 Platform), Java a fost extins,
acoperind si mai multe directii de dezvoltare: programarea aplicatiilor enterprise (aplicatii de tip
server) precum si a celor adresate dispozitivelor cu resurse limitate, cum ar fi telefoanele mobile.
Avantajele:
- Java este un limbaj simplu de folosit. Aceasta caracteristica poate fi considerata ca o reactie directa
la complexitatea considerabila a limbajului C/C++. Au fost indepartate din Java aspectele cele mai
derutante din C++ precum supraincarcarea operatorilor, mostenirea multipla sau pointer-rii.
- Java este independent de arhitectura calculatorului pe care lucreaza si foarte portabil. Compilatorul
Java genereaza o secventa de instructiuni ale unei masini virtuale Java. Executia aplicatiilor Java
este interpretata. Singura parte din mediul de executie Java (JRE) care trebuie portata de pe o
arhitectura pe alta cuprinde interpretorul Java si o parte din bibliotecile standard care depind de
sistem. In acest fel aplicatii Java compilate pe o arhitectura SPARC de exemplu, pot fi rulate fara
recompilare pe un sistem bazat pe procesoare Intel. De altfel, mediul de executie Java (JRE) este
scris in C ceea ce il face foarte portabil.
- Interpretorul Java este gandit sa lucreze pe masini mici (memorie mica de ordinul sutelor de KB),
precum ar fi procesoarele cu care sunt dotate aparatele casnice si telefoanele mobile.
- Limbajul Java este orientat obiect. Cu el se pot crea clase de obiecte si instante ale acestora, se pot
incapsula informatiile, se pot mosteni variabilele si metodele de la o clasa la alta etc. Singura
caracteristica care lipseste este mostenirea multipla, dar pentru a suplini aceasta lipsa, Java ofera o
facilitate mai simpla, numita interfata, care permite definirea unui anumit comportament pentru o
clasa de obiecte, altul decat cel definit de clasa de baza. In Java orice element este un obiect, in afara
de datele primare. Din Java lipsesc functiile si variabilele globale.
- Limbajul Java este distribuit, avand implementate biblioteci pentru lucrul in retea.
- Limbajul Java este un limbaj cu securitate ridicata.
- Java are inclus suport nativ pentru aplicatii care lucreaza cu mai multe fire de executie (programare
paralela si concurenta). Acest suport este independent de sistemul de operare.
2. Structura unui program Java, funcția „main”, clase statice, tipul „void”
O aplicatie Java este compusa din una sau mai multe clase care interactioneaza intre ele prin
intermediul metodelor. In grupul de clase, care formeaza o aplicatie Java, trebuie sa existe o clasa
care sa contina o metoda statica avand numele main.
Cel mai simplu program Java arata astfel:
class aplicatie
{
public static void main (String [ ] args)
{System.out.println(“Primul program Java”);}
}
metoda “main ()” este este declarată cu trei cuvinte cheie: public, static și void:
- public : această metodă este publică și, prin urmare, este disponibilă pentru oricine.
- static : această metodă poate fi rulată fără a fi nevoie să creați o instanță din clasa MyClass.
- void : această metodă nu returnează nimic.
- (String [] args) : Această metodă acceptă un argument String. Rețineți că argumentul args
poate fi orice - este obișnuit să folosiți „args”, dar în schimb l-am putea numi „stringArray”.
3. Tipuri de date primitive în limbajul de programare Java
Un tip de date defineste multimea de valori pe care variabila poate sa le stocheze, modul de
reprezentare a acestora in memorie, ca si setul de operatii pe care programul poate sa le realizeze cu
aceste date.
In limbajul Java a fost exact definita modalitatea de reprezentare a tipurilor primitive de date in
memorie. In acest fel, variabilele Java devin independente de platforma hardware si software pe care
lucreaza.
De asemenea, Java defineste o valoare implicita pentru fiecare tip de date, in cazul in care variabila
de un anumit tip nu a primit nici o valoare de la utilizator. Este o practica buna insa aceea ca
programele sa nu depinda niciodata de aceste initializari implicite.
Limbajul Java accepta urmatoarele tipuri de baza: byte, short, int, long, float, double, char, boolean,
void.
Tabelul de mai jos prezinta o descrie generala a tipurilor primitive de date utilizate de Java:

Type Size (bits) Minimum Maximum Example

byte 8 -27 27– 1 byte b = 100;

short 16 -215 215– 1 short s = 30_000;

int 32 -231 231– 1 int i = 100_000_000;

long 64 -263 263– 1 long l = 100_000_000_000_000;

float 32 -2-149 (2-2-23)·2127 float f = 1.456f;

double 64 -2-1074 (2-2-52)·21023 double f = 1.456789012345678;

char 16 0 216– 1 char c = ‘c';

boolean 1 – – boolean b = true;


4. Metode (funcții) de prelucrare a numerelor întregi și reale în limbajul de programare
Java (1)
Functii aritmetice:
The Java “Math” class provides more advanced mathematical calculations than what the basic Java
math operators provide. The Math class contains methods for finding the maximum or minimum of
two values, rounding values, logarithmic functions, square root, and trigonometric functions (sin,
cos, tan etc.).
Basic “Math” functions:
Math.abs()
The Math.abs() function returns the absolute value of the parameter passed to it. The absolute value
is the positive value of the parameter. If the parameter value is negative, the negative sign is
removed and the positive value corresponding to the negative value without sign is returned. Here
are two Math.abs() method examples:
int abs1 = Math.abs(10); // abs1 = 10
int abs2 = Math.abs(-20); // abs2 = 20
Math.ceil()
The Math.ceil() function rounds a floating point value up to the nearest integer value. The rounded
value is returned as a double. Here is a Math.ceil() example:
double ceil = Math.ceil(7.343); // ceil = 8.0
Math.floor()
The Math.floor() function rounds a floating point value down to the nearest integer value. The
rounded value is returned as a double. Here is a Math.floor() Java example:
double floor = Math.floor(7.343); // floor = 7.0
Math.floorDiv()
The Math.floorDiv() method divides one integer (int or long) by another, and rounds the result down
to the nearest integer value.
double result3 = Math.floorDiv(-100,9);
System.out.println("result3: " + result3);
The output printed from this Java code is:
result3: -12.0
4. Metode (funcții) de prelucrare a numerelor întregi și reale în limbajul de programare Java (2)
Math.min()
The Math.min() method returns the smallest of two values passed to it as parameter:
int min = Math.min(10, 20);
After executing this code the min variable will contain the value 10.
Math.max()
The Math.max() method returns the largest of two values passed to it as parameter:
int max = Math.max(10, 20);
After executing this code the max variable will contain the value 20.
Math.round()
The Math.round() method rounds a float or double to the nearest integer using normal math round
rules (either up or down):
double roundedDown = Math.round(23.445);
double roundedUp = Math.round(23.545);
After executing these two Java statements the roundedDown variable will contain the value 23.0 ,
and the roundedUp variable will contain the value 24.0.
Math.random()
The Math.random() method returns a random floating point number between 0 and 1:
double random = Math.random();
5. Descrierea și inițializarea variabilelor în limbajul de programare Java
O variabilă este un container care conține valori care sunt utilizate într-un program Java . Pentru a
putea folosi o variabilă trebuie să fie declarată. Declararea variabilelor este în mod normal primul
lucru care se întâmplă în orice program.
Pentru a declara o variabilă în Java, tot ce este necesar este tipul de date urmat de numele variabilei :
int numberOfDays;
Înainte de a putea fi utilizată o variabilă, trebuie să i se acorde o valoare inițială. Aceasta se numește
inițializarea variabilei.
Pentru a inițializa o variabilă, folosim o declarație de atribuire. O declarație de atribuire urmează
același model ca o ecuație în matematică. Există o parte stângă a ecuației, o parte dreaptă și un semn
egal (adică "=") în mijloc. Pentru a da o valoare unei variabile, partea stângă este numele variabilei,
iar partea dreaptă este valoarea:
int numberOfDays;
numberOfDays = 7;
De obicei, inițializarea unei variabile se face în același timp cu declarația sa:
int numberOfDays = 7;
Există anumite reguli pentru numele unei variabile:
- cuvintele rezervate nu pot fi folosite.
- nu pot începe cu o cifră
- pot începe cu o literă, o subliniere (adică „_”) sau un semn de dolar (adică „$”)
- nu puteți contine alte simboluri sau spații (de ex., "%", "^", "#")
Tipul variabilelor:
- Variabilă locală - aceste variabile sunt declarate în corpul unei metode. Acestea pot fi
utilizate în cadrul aceleiași metode în care este inițializată.
- Variabila de instanta - sunt acele variabile care sunt declarate în interiorul unei clase. Spre
deosebire de variabilele locale, aceste variabile nu pot fi declarate într-un bloc, metodă sau
constructor
- Variabilă statică sau de clasă - tip de variabilă care este declarat ca static (static int
num1;)
6. Afișarea informației pe ecran și citirea datelor de la tastatură în limbajul Java
In limbajul Java nu exista instructiuni specializate pentru citirea/scrierea datelor. Intrarea si iesirea in
Java se realizeaza cu ajutorul claselor de obiecte din pachetul predefinit java.io. Orice program care
foloseste elemente de intrare/iesire trebuie sa cuprinda instructiunea: import java.io.*
Java ofera trei fluxuri predefinite pentru operatii I/O standard:
- System.in pentru intrarea standard de la tastatura;
- System.out pentru iesirea standard la ecranul calculatorului;
- System.err pentru fluxul de erori.
Pentru afisarea datelor la ecranul calculatorului se folosesc metodele “print” si “println”:
- System.out.print (<expresie>);
- System.out.println (<expresie>);
Efectul apelului metodei println este acela ca se realizeaza afisarea la ecran a variabilei data ca
parametru si se face salt la o linie noua. Metoda println se poate apela si fara parametrii, adica in
forma: System.out.println( );
caz in care se face numai un salt la o linie noua fara sa se afiseze nimic
Citirea datelor de la tastatura se realizeaza cu metoda “readLine”. Insa pentru citire trebuie sa
construim un obiect “BufferedReader” dintr-un obiect “InputStreamReader” care la randul sau este
construit din “System.in”.
Sintaxa folosita la apelul metodei “readLine” este: <nume_obiect>.readLine(); unde:
<nume_obiect> - reprezinta o variabila de tipul obiectului “BufferedReader”
Exemplu de program cu functii de intrare/iesire:
import java.io.*;
public class Afiseaza
{ public static void main(String[] args) throws IOException {
System.out.println("Bun venit in universul Java");
System.out.print ("Introduceti un numar ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
int a = Integer.parseInt(s);
System.out.println(s);
}}
7. Operatori aritmetici, operatori de atribuire, de incrementare și de decrementare în Java
Operatorii aritmetici sunt: ‘*’ - inmultirea; ‘/’ - impartirea; ‘%’ - restul impartirii intregi; ‘+’ -
adunarea; ‘-’ - scaderea.
Operatorul de incrementare este ‘++’. Operatorul de decrementare este ‘--’. Acesti operatori sunt
unari si au ca efect marirea (respectiv micsorarea) valorii operandului cu 1.
Limbajul Java permite doua forme pentru operatorii de incrementare / decrementare: forma prefixata
(inaintea operandului) si forma postfixata (dupa operand).
In cazul cand se foloseste operatorul de incrementare / decrementare in forma prefixata (inaintea
operandului), limbajul Java va incrementa / decrementa mai intai valoarea variabilei si apoi va
utiliza variabila intr-o alta expresie.
In cazul cand se foloseste operatorul de incrementare / decrementare in forma postfixata (dupa
operand), limbajul Java va utiliza mai intai valoarea variabilei intr-o alta expresie si apoi va efectua
operatia de incrementare / decrementare.
De exemplu, daca valoarea curenta a lui x este 4, atunci:
- evaluarea expresiei 3 * ++x conduce la rezultatul 15;
- evaluarea expresiei 3 * x++ conduce la rezultatul 12,
dupa care valoarea lui x va fi in ambele cazuri 5.
Operatorii de incrementare / decrementare pot fi aplicati numerelor intregi, reali si variabilelor de
tipul char.
Operatorii de atribuire sunt operatori binari care permit modificarea valorii unei variabile. Exista un
operator de atribuire simplu (=) si operatori de atribuire compusi cu ajutorul operatorului ‘=‘ si al
unui alt operator binar (aritmetic sau logic pe biti): {*, /, %, +, -, <<, >>, &, |, ^}.
O varianta de sintaxa folosita este:
<nume_variabila> = <expresie>
Efectul aplicarii operatorului este: Se evalueaza <expresie>, apoi se atribuie variabilei
<nume_variabila> valoarea expresiei.
Exemple:
total = total + 100; total+ =100;
jumatate = jumatate/2; jumatate/ =2;
b = a = a*2; b = a* = 2;
8. Operatori relaționali, operatori logici și operatorul condițional în limbajul Java
Operatorii relationali sunt operatori binari si desemneaza relatia de ordine in care se gasesc cei doi
operanzi: <, >, <=, >=.
Rezultatul aplicarii unui operator relational este true daca cei doi operanzi sunt in relatia indicata de
operator, si false, altfel.
De exemplu, expresiile logice:
- 5> 7 are ca rezultat valoarea false
- 9 <= 3+14 are ca rezultat valoarea true
Exista trei operatori logici:
- negatia logica (not) reprezentata cu !
- conjunctie logica (si) reprezentata cu &&
- disjunctie logica (sau) reprezentata cu | |
There are three types of the conditional operators in Java:
o Conditional AND

o Conditional OR
o Ternary operator

Operator Symbol

Conditional or Logical AND &&

Conditional or Logical OR ||

Ternary Operator ?:

The meaning of ternary is composed of three parts. The ternary operator (? :) consists of three
operands. It is used to evaluate Boolean expressions.
variable = (condition) ? expression1 : expression2
The above statement states that if the condition returns true, expression1 gets executed, else the
expression2 gets executed and the final result stored in a variable.
9. Operatori la nivel de bit în limbajul de programare Java, prioritatea operațiilor, utilizarea
parantezelor pentru a modifica ordinea de efectuare a lor (1)
Operatorii pe biţi acţionează asupra biţilor valorilor întregi (int şi long).
Operator Nume Descriere
a&b și 1 dacă ambii biţi au valoarea 1.
a|b sau 1 dacă cel puţin un bit are valoarea 1.
a^b sau exclusiv 1 dacă biţii au valori diferite.
~a complement Inversează valoarea biţilor.
n << p deplasare Deplasează biţii lui n la stânga cu p poziţii.
stânga fără
semn
n >> p deplasare Deplasează biţii lui n la dreapta cu p poziţii.
dreapta cu
semn

Evaluarea operatorilor în Java are loc conform priorității operatorului, adică evaluarea are loc
începând cu operatorii cu prioritate mai mare și este urmată de operatorii cu prioritate relativ mai
mică.

Operatori Precedența operatorilor Asociativitate

Postfix expr ++ expr-- De la stânga la dreapta

Unar ++ expr --expr + expr -expr ~! De la dreapta la stanga

Multiplicativ * /% De la stânga la dreapta

Aditiv +- De la stânga la dreapta

Schimb <>>>> De la stânga la dreapta

Relațional = instanceof De la stânga la dreapta

Egalitate ==! = De la stânga la dreapta

Bitwise ȘI & De la stânga la dreapta


SAU exclusiv bit ^ De la stânga la dreapta

Incluziv pe biți SAU | De la stânga la dreapta

logic ȘI && De la stânga la dreapta

OR logic || De la stânga la dreapta

Ternar ?: De la dreapta la stanga

9. Operatori la nivel de bit în limbajul de programare Java, prioritatea operațiilor, utilizarea


parantezelor pentru a modifica ordinea de efectuare a lor (2)
Parantezele () au trei utilizări:
1. Gruparea pentru a controla ordinea de evaluare sau pentru claritate.
Exemplu: (a + b) * (c - d)

2. După o metodă pentru a cuprinde parametrii. Exemplu: x = suma(a, b);


3. În jurul unui tip pentru a forma determina o conversie explicită (tip). Exemplu: i = (int)x;
10. Instrucțiuni condiționale în limbajul de programare Java
Instructiunile conditionale determina programele sa testeze diferite conditii si in functie de acestea
sa decida executia anumitor comenzi. Aceste instructiuni conditionale sunt:
- if() - executa comenzile dorite cand o conditie scrisa in paranteze este adevarata.
- if() ... else - executa anumite comenzi cand o conditie este adevarata si alte comenzi cand
aceasta este falsa.
- switch - selecteaza care comanda va fi executata.
Instructiunea "if" - forma generala a acestei instructiuni este urmatoarea :
if (conditie) { // Codul care va fi executat daca este Adevarata conditia }
Instructiunea "if ... else" - folosind combinatia "if() ... else", putem stabili comenzi care sa fie
executate si cand conditia instructiunii "if()" este FALSEȘ
if (conditie) { // codul care va fi executat daca este Adevarata conditia }
else { // codul ce va fi executat daca conditia este falsa }
Daca rezultatul conditiei este TRUE se executa codul dintre primele acolade, care apartin de "if()",
in caz contrar, cand conditia returneaza FALSE, sunt executate comenzile din acoladele de la "else":
Formula "else if()" – se folosește pentru a oferi mai multe opțiuni:
if (conditie 1) { // codul care va fi executat daca este adevarata conditia 1 }
else if (conditie 2) { // codul ce va fi executat daca prima conditie este falsa si este adevarata
conditia 2 }
else if (conditie 3) { // codul care va fi executat daca primele doua conditii sunt False si este
Adevarata conditia 3 }
// ... else { // codul executat daca toate conditiile sunt false }
Instructiunea switch - este folosita pentru a compara o valoare cu altele dintr-o lista, si in functie de
acea valoare se executa codul asociat ei in lista "switch":
switch (expresie) { case valoare1: cod executat daca expresie = valoare1 break;
case valoare2: cod executat daca expresie = valoare2 break;
case valoare3: cod executat pt. expresie = valoare3 break;
default : cod executat daca expresie e diferit de valoare1, valoare2 sau valoare3 }
- Prima data este evaluata expresia scrisa intre paranteze rotunde, la "switch()", apoi valoarea
expresiei este comparata pe rand cu fiecare valoare determinata de "case". Daca, parcurgand fiecare
"case", nu se gaseste o egalitate, se executa codul de la "default".
Prin folosirea lui "break" se opreste parcurgerea corpului instructiunii atunci cand s-a gasit o valoare
egala cu 'expresie' si se iese din "switch".
11. Cicluri în limbajul de programare Java
Instructiunile repetitive se folosesc atunci cand se doreste efectuarea unei comenzi de mai multe
ori. In java putem folosi urmatoarele instructiuni ciclice:
The while loop loops through a block of code as long as a specified condition is true:
while (condition) { // code block to be executed }
Example:
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
The do/while loop is a variant of the while loop. This loop will execute the code block once, before
checking if the condition is true, then it will repeat the loop as long as the condition is true.
do { // code block to be executed }
while (condition);
“For” loop - hen you know exactly how many times you want to loop through a block of code, use
the for loop instead of a while loop:
for (statement 1; statement 2; statement 3) { // code block to be executed }
Statement 1 is executed (one time) before the execution of the code block.
Statement 2 defines the condition for executing the code block.
Statement 3 is executed (every time) after the code block has been executed.
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
12. Tablouri unidimensionale în limbajul de programare Java: declararea, inițializarea, etc.
Un tablou este o structura de date care poate sa pastreze mai multe valori de acelasi tip.
Declararea si crearea tablourilor unidimensionale se realizeaza in doi pasi:
1. Se declara o variabila referinta la tablou

<tip> <nume_tablou> [ ]; sau <tip> [ ] <nume_tablou>;

2. Se aloca, efectiv, zona de memorie pentru tabloul declarat la pasul 1 si se initializeaza


tabloul.
Exista doua modalitati pentru a face acest lucu:
a) folosind operatorul new - <nume_tablou> = new <tip> [<nr_elem>];
Este posibil de declarat și de inițiat tabloul în aceeasși comandă:
<tip> <nume_tablou> [ ] = new <tip> [<nr_elem>]; sau <tip> [ ] <nume_tablou> = new <tip>
[<nr_elem>];
Alocarea de memorie se face prin atribuire valorilor la tabloul inițializat.
Exemplu:
int [ ] temp = new int[100];
int [ ] temp = {3, 4, 7, 15};
b) initializand direct continutul tabloului: <tip> [ ] <nume_tablou>; <nume_tablou> = {<valoare1>,
<valoare2>, ….}; sau <tip> [ ] <nume_tablou> = {<valoare1>, <valoare2>, ….};
Tablourile Java sunt alocate dinamic, ceea ce inseamna ca ele isi pot schimba dimensiunile pe
parcursul executiei programului. Numarul de elemente care sunt stocate intr-un tablou se poare afla
prin folosirea metodei <nume_tablou>.length.
Exemplu:
float [] tablou = new float [21];
int dimensiune = tablou.length;
Pentru a accesa un element al unui tablou se specifica numele tabloului din care face parte
elementul si pozitia sa in tablou, prin numarul sau de ordine (numerotarea incepe de la 0):
<nume_tablou>[<indice>]
13. Prelucrarea tablourilor unidimensionale în limbajul de programare Java (determinarea
sumei/ produsului, elementului maxim/ minim, parcurgerea, etc.)
Prelucratea tablourilor se efectuiază prin folosirea proprietășilor și a metodelor specifice tablourilor,
în dependența de rezultatul care trebuie să fie obținutt.
- Determinarea sumei elementelor unui tablou:
public static int suma(int[] array) {
int suma1 = 0;
for (int value : array) {
suma1 = suma1 + value; }
return suma1; }
- Determinarea produsului elementelor unui tablou:
public static int produs(int[] array) {
int produs1 = 1;
for (int value : array) {
produs1 = produs1 * value; }
return produs1; }
- Determinarea elementului maxim/ minim
int[] nums={6,-1,-2,-3,0,1,2,3,4};
Arrays.sort(nums);
System.out.println("Minimum = " + nums[0]);
System.out.println("Maximum = " + nums[nums.length-1]);
You will need to import “java.util.*” package to use “Arrays” class.
Parcurgerea unui tablou reprezintă referirea fiecărui element al tabloului, într-o anumită ordine.
Referirea elementului se face prin intermediul indicelui, cu ajutorul operatorului de indexare.
Următorul exemplu declară un tablou cu 100 de elemente și memorează în primele n elemente ale
tabloului valoarea 1:
int x[100], n;
for(int i = 0 ; i < n ; i ++)
x[i] = 1;
14. Tablouri bidimensionale în limbajul de programare Java: declararea, inițializarea, etc.
Tablourile bidimensionale reprezintă o structură de tablouri unidimensionale referite către alte
tablouri unidimensionale.
Declararea si crearea tablourilor bidimensionale se realizeaza in doi pasi:
1. declararea tabloului de un anumit tip
<tip> <nume_tablou> [ ][ ]; sau <tip> [ ][ ] <nume_tablou>; sau <tip> [ ] <nume_tablou> [ ];
unde:
- <tip> - specifica tipul de date al elementelor tabloului
- <nume_tablou> - reprezinta numele tabloului
2. alocarea zonei de memorie pentru tabloul declarat si initializarea lui
Alocarea zonei de memorie pentru tabloul declarat si initializarea lui se face in doua feluri:
a) folosind operatorul new
<nume_tablou> = new <tip>
[<nr_linii>][<nr_coloane>];
De cele mai multe ori programatorii combina declararea si alocarea zonei de memorie pentru un
tablou intr-o singura instructiune:
<tip> <nume_tablou> [ ][ ] = new <tip> [<nr_linii>][<nr_coloane>];
exemplu: char [][] caractere = new char [5][];

! when you initially declare a two-dimensional array, you must remember to specify the first
dimension
b) initializand direct conținutul tabloului
Ex: pentru declarea si alocarea zonei de memorie pentru un tablou bidimensional cu numele b de tip
int cu doua linii si trei coloane se foloseste instructiunea:
int b[][]={{1, 2, 3}, {7, 8, 9}};
Pentru eliberarea memoriei ocupate de un tablou, este suficient sa anulam toate referintele catre
tablou.
15. Tablouri bidimensionale pătratice, tablouri bidimensionale în care fiecare rând are
număr diferit de coloane
Un tablou pătratic este o matrice care are numarul de linii egal cu numarul de coloane. Matricele
patratice sunt un caz aparte al matricelor oarecare doarece in cazul acestora apar doua diagonale.
Una din aceste diagonale se numeste diagonala principala, iar cealalta diagonala secundara.
Pentru a identifica elementele acestore diagonale, putem folosi următoarele progame:
- Elementele diagonalei principale:
static void printPrincipalDiagonal(int mat[][], int n)
{ System.out.print("Principal Diagonal: ");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// Condition for principal diagonal
if (i == j) {
System.out.print(mat[i][j] + ", "); }}}
System.out.println(""); }
- Elementele diagonalei secundare:
static void printSecondaryDiagonal(int mat[][], int n) {
System.out.print("Secondary Diagonal: ");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// Condition for secondary diagonal
if ((i + j) == (n - 1)) {
System.out.print(mat[i][j] + ", "); } } }
System.out.println(""); }
Tablourile bidimensionale pot avea un număr de rînduri/coloane diferite. Pentru acest tip de tablouri
e relevantă metoda de calculare a lungimii rîndului/coloanei:
Numarul de linii care poate fi stocat într-un tablou bidimensional, este permanent retinut in variabila
<nume_tablou>.length
Numarul de coloane ale fiecarei linii (i) este permament retinut in variabila <nume_tablou>[i].length
Accesarea unui element al tabloului bidimensional se face prin următoare instrucțiune:
<nume_tablou> [<indice_linie>] [<indice_coloana] (ex: int a[4][3];)
16. Prelucrarea tablourilor bidimensionale în limbajul de programare Java (determinarea
sumei/ produsului, elementului maxim/ minim, parcurgerea, etc.)
Prelucratea tablourilor bidimensionale se efectuiază prin folosirea proprietășilor și a metodelor
specifice tablourilor, în dependența de rezultatul care trebuie să fie obținutt.
- Determinarea sumei elementelor unui tablou bidimensional:
public static int suma(int[][] array) {
int suma1 = 0;
for (int row=0; row < array.length; ++row) {
for(int col=0; col<array[row].length; ++col) {
suma1 = suma1 + array[row][col]; }
} return sum1; }
- Determinarea produsului elementelor unui tablou:
public static int produs(int[][] array) {
int produs1 = 1;
for (int row=0; row < array.length; ++row) {
for(int col=0; col<array[row].length; ++col) {
produs1= produs1 * array[row][col]; }
} return sum1; }
- Determinarea elementului minim
min = matrix[3][2];
for(int i=0; i<numRows; i++) {
for(int j=0; j<numCols; j++) {
if(matrix[i][j] < min)
min = matrix[i][j]; } }
Parcurgerea presupune accesarea elementelor ale tabloului, într-o anumită ordine – de regulă
aceasta se face pe linii, de sus în jos și de la stânga la dreapta:
int n, m, a[100][100]; ...
for(int i = 0 ; i < n ; i ++) {
// linia i
for(int j = 0 ; j < m ; j ++)
// a[i][j] // … }
17. Tablouri multidimensionale (tridimensionale ș.a.) în limbajul de programare Java
Tablourile multidimensionale sunt vectori de tablouri și au următpare structură:
tip tablou[][][] = new tip[dim1][dim2][dim3];
De exemplu, arr[i][j][k] este echivalent cu ((arr[i])[j])[k]. Respectiv, arr este o matrice, de matrice,
de matrice.
In a 3d array, the three dimensions are interpreted as:
- number of arrays: the first dimension indicates how many arrays a 3d array will have
- number of rows: the second dimension signifies the total number of rows an array will have
- number of columns: the third dimension indicates the total columns in the 3d array
Declaraţie:
int[][][] threeDimArr = new int[4][5][6];
sau, cu inițializare:
int[][][] threeDimArr = { { { 1, 2 }, { 3, 4 } }, { { 5, 6 }, { 7,
8 } } };
Acces:
int x = threeDimArr[1][0][1];

sau
int[][] row = threeDimArr[1];
18. Proprietatea „length”, forma specială a ciclului „for” pentru tablouri (similar for-each
din alte limbaje).
The array length is the number of elements that an array can holds. We can find the array length by
using the array attribute “length”. We use this attribute with the array name:
int lungime= matrice.length;
Length size implies the total number of elements that an array can contain. The “length” property
can be invoked by using the dot (.) operator followed by the array name. We can find the length of
int[], double[], String[], etc:
int[] arr=new int[5];
int arrayLength=arr.length
In the above code snippet, arr is an array of type int that can hold 5 elements. The “arrayLength” is a
variable that stores the length of an array. To find the length of the array, we have used array name
(arr) followed by the dot operator and “length” attribute, respectively. It determines the size of the
array.
Important: “length” attribute determines the maximum number of elements that the array can
contain or the capacity of the array. It does not count the elements that are inserted into the array.
That is, length returns the total size of the array. For arrays whose elements are initialized at the time
of its creation, length and size are the same.
Speaking about the logical size, array index will always be less than the actual size by 1 (int
arrayLength=arr.length-1), because the array index starts from 0.
Atributul length poate fi utilizat pentru a căuta o anumită valoare în matrice sau pentru a căuta
valorile minime / maxime.
19. Sortarea tablourilor în limbajul de programare Java
The sorting is a way to arrange elements of a list or array in a certain order (ascending or
descending)
For sorting an array in an ascending order, we may use the “sort()” method
sort() - it is a static method that parses an array as a parameter and does not return anything. We can
invoke it directly using the class name. It accepts an array of type int, float, double, long, char, byte.
Example:
import java.util.Arrays;
public class SortArrayExample1 {
public static void main(String[] args) {
//defining an array of integer type
int [] array = new int [] {90, 23, 5, 109, 12, 22, 67, 34};
//invoking sort() method of the Arrays class
Arrays.sort(array);
System.out.println("Elements of array sorted in ascending order:
");
//prints array using the for loop
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]); } } }
For sorting an array in an descending order, we may use “reverseOrder()” method. It does not parse
any parameter. It returns a comparator that imposes the reverse of the ascending ordering.
Example:
import java.util.Arrays;
import java.util.Collections;
public class SortArrayExample4 {
public static void main(String[] args) {
Integer [] array = {23, -9, 78, 102, 4, 0, -1, 11, 6, 110, 205};
// sorts array[] in descending order
Arrays.sort(array, Collections.reverseOrder());
System.out.println("Array elements in descending order: "
+Arrays.toString(array)); } }
20. Șiruri de caractere (Clasele String, StringBuffer și StringBuilder) în limbajul de
programare Java: declararea, inițializarea, modificarea etc., deosebirile între clasele
„String”, „StringBuffer” și „StringBuilder
Valorile șir de caractere sunt gestionate de tipul de date “string”. Acestea pot fi create utilizand
sintaxa implicită, bazată pe new:
String s = new String();
String sCuValoare = new String("Salut String!" );
Sirurile de caractere sunt obiecte. Atunci cand se utilizeaza semnul egal (=) intre 2 obiecte de tip
string, veti copia valoarea referinței la obiect, ci nu valoarea obiectului:
String string1 = "Hello Strings";
String string2 = string1; // string 2 va avea valoarea referinței la obiectul string1
Obiectul inițială de tip “string” (string1) nu-si modifica valoarea după ce a fost creat.
Clasele “StringBuffer” si “StringBuilder” sunt folosite pentru a face obiectele “String” mutable. Prin
urmare, aceste obiecte pot fi modificate. Obiectele de caractere create cu aceste clase pot economisi
memorie. StringBuffer asigură siguranța firelor, deoarece două fire nu pot accesa simultan aceeași
metodă în clasa StringBuffer. Aceasta proprietate poate reduce performanța. Clasele “StringBuffer”
si “StringBuilder” conțin metode cum ar fi append (), insert (), invers (), replace ().
Diferente generale intre sir de caractere, stringbuffer si stringbuilder
Șirul este o clasă Java care este utilizată pentru a crea un obiect de tip String, care este o secvență de
caractere.
StringBuffer este o clasă Java care este utilizată pentru a crea obiecte String, care pot fi modificate
cu siguranța firelor.
StringBuilder este o clasă care este utilizată pentru a crea obiecte șir, care pot fi modificate fără
siguranța firului.
Mutabilitate
Șirul este o clasă imuabilă. | StringBuffer este o clasă mutable. | StringBuilder este o clasă mutable.
Securitatea filetului
Metodele de șir sunt sigure. | Metodele lui StringBuffer sunt sigure și sincronizate cu fir. |
Metodele lui StringBuilder nu sunt sigure și nu sunt sincronizate.
Performanţă
Șirul este rapid. | StringBuffer este lent. | StringBuilder este rapid.
21. Principalele metode folosite la prelucrarea șirurilor de caractere în limbajul Java
Clasa “String” are mai multe metode pentru a prelucra o valoare. Cele mai utilizate sunt:
charAt() - întoarce caracterul aflat la un anumit indice; indicele ia valori de la 0 la length()-1;
concat() - concateneaza un string la sfarsitul celui existent; la fel ca +;
equals() - compara la nivel de caracter 2 valori string; face diferenta intre litere mici si mari
length() - returneaza numarul de caractere; este diferit de atributul “length” al unui vector (e o
metoda)
replace() - înlocuiește aparițiile unui caracter cu unul primit
substring() - returneaza un subsir
toLowerCase() - converteste toate caractere la litere mici
toString() - returnează valoarea obiectului String
toUpperCase() - converteste toate caractere la majuscule
trim () - elimina spațiul de la sfârșitul șirului de caractere
Este important de ținut minte ca unele dintre aceste metode creaza un nou obiect de tip string, în loc
sa modifice obiectul curent.
Exemplu:
String text1 = "TEST" ;
text1.toLowerCase(); //rezultatul este un alt string
22. Avantajele programării orientate pe obiecte

Programarea orientată pe obiect (Programare Orientată Obiectual) este unul din cei mai importanți
pași făcuți în evoluția limbajelor de programare spre o mai puternică abstractizare în implementarea
programelor. Ea a apărut din necesitatea exprimării problemei într-un mod mai simplu, pentru a
putea fi înțeleasă de cât mai mulți programatori. Astfel unitățile care alcătuiesc un program se
apropie mai mult de modul nostru de a gândi decât modul de lucru al calculatorului.

Până la apariția programării orientate pe obiect, programele erau implementate în limbaje de


programare procedurale. O mare problemă a programării procedurale era separarea datelor de
unitățile care prelucrau datele (subrutinele), ceea ce făcea foarte dificilă extinderea și întreținerea
unui program. Astfel s-a pus problema ca aceste două entități (date și subrutine) să fie grupate într-
un anumit mod, astfel încât subrutinele să "știe" în permanență ce date prelucrează și, mai mult decât
atât, ele să formeze un modul, adică o unitate care separă implementarea de interfață, ceea ce
implică posibilitatea refolosirii codului. A apărut astfel conceptul de clasă.

Clasele grupează datele și unitățile de prelucrare a acestora într-un modul, unindu-le astfel într-o
entitate mult mai naturală. Deși tehnica se numește "Programare Orientată Obiectual", conceptul de
bază al ei este Clasa. Clasa, pe lângă faptul că abstractizează foarte mult analiza/sinteza problemei,
are proprietatea de generalitate, ea desemnând o mulțime de obiecte care împart o serie de
proprietăți.

Beneficiile Programarii Orientate pe Obiecte:

● Modularitatea: codul sursa pentru o clasa poate fi scris si mentinut independent de codul
sursa pentru alte clase. Odata creat, un obiect poate fi usor transferat in interiorul sistemului

● Securitate ridicata la nivel de cod: Interactionand doar cu metodele obiectului, detaliile


implementarii interne raman ascunse de lumea exterioara.

● Reutilizarea codului: daca o clasa exista deja, puteti utiliza in programul dvs. obiecte din
acea clasa. Acest lucru permite programatorilor sa implementeze / testa / depana obiecte
complexe, specifice pentru sarcini, pe care apoi le puteti folosi in propriul cod.

● Debugging mai usor: Daca un anumit obiect se dovedeste a fi o problema, il puteti elimina
din program si puteti adauga/conecta, ca inlocuitor, un obiect diferit. Acest lucru este similar
cu rezolvarea problemelor mecanice in lumea reala. Daca un surub se rupe, il inlocuiti pe el,
nu intreaga masina.
23. Clase: declararea, operatori de protecție, set-teri și get-teri
Clasele reprezinta principiile de baza ale programarii orientate obiect. Clasele reprezinta notiuni
abstracte, modele (blueprints), ce descriu:

- caracteristicile, atributele unui obiect; reprezinta ceea ce stie sau ce este obiectul;
- ce stie sa faca obiectul, comportamentul acestuia descris de metodele sale;

1. Sintaxa generala prin care se defineste o clasa in Java este:

[modificator_acces] class nume_clasa [extends base_class]{

// bloc clasa

Modificatorii de access utilizati pentru membrii unei clase (metode si atribute) sunt:

- public: Orice clasa poate crea instante ale clasei respective


- protected: Doar subclasele pot crea obiecte de tipul clasei respective
- default: Doar clasele din acelasi pachet pot crea instante ale clasei respective
- private: Nici o alta clasa nu poate instantia obiecte ale acestei clase

Asa cum reiese din scurta descriere a modificatorilor de acces, acestia reprezinta reguli cu privire la
dreptul de a accesa membrii (atribute si metode) unei clase din alte clase.

2. Set-teri si Get-teri

În Java, Set-teri si Get-teri sunt două metode convenționale care sunt folosite pentru returnarea și
actualizarea valorilor variabilelor din cadrul unei clase. Sunt folositi pentru a evita expunerea
variabilelor in exteriorul clasei.

public String getName() { public void setName(String name) {


return this.name; this.name = name;
} }
24. Crearea obiectelor unei clase, operatorul „new”, Garbage Collector; metoda „finalize()”
In Java obiectele sunt create prin instantierea unei clase, cu alte cuvinte prin crearea unei instante a
unei clase. Crearea unui obiect presupune trei lucruri:
1. Declararea obiectului: NumeClasa numeObiect; Ex: Rectangle patrat;
2. Instantierea: Se realizeaza prin intermediul operatorului new si are ca efect crearea
efectiva a obiectului cu alocarea spatiului de memorie corespunzator.
Ex: patrat = new Rectangle();

3. Initializarea: Se realizeaza prin intermediul constructorilor clasei respective. Rectangle()


este un apel catre constructorul clasei Rectangle care este responsabil cu initializarea
obiectului. Initializarea se poate face si cu anumiti parametri, cu conditia sa existe un
constructor al clasei respective care sa accepte parametrii respectivi.
Ex: patrat = new Rectangle(0, 0, 100, 200);
Declararea, instantierea si initializarea obiectului pot aparea pe aceesi linie (cazul cel mai uzual):
Rectangle patrat = new Rectangle(0, 0, 100, 200);
Distrugerea obiectelor:
In Java programatorul nu are responsabilitatea distrugerii obiectelor sale întrucât, în momentul
rularii unui program, simultan cu interpretorul Java ruleaza si un proces care se ocupa cu distrugerea
obiectelor care nu mai sunt folosite. Acest proces pus la dispozitie de platforma Java de lucru se
numeste garbage collector (colector de gunoi), prescurtat gc.
Un obiect este elimnat din memorie de procesul de colectare atunci când nu mai exista nici o
referinta la acesta. Referintele (care sun de fapt variabile) sunt distruse în mod :
-natural, atunci când variabila respectiva iese din domeniul sau, de exemplu la terminarea
unei metode
-explicit, daca atribuim variabilei respective valoare null.
Finalizarea:
Inainte ca un obiect sa fie eliminat din memorie, procesul gc da acelui obiect posibilitatea "sa curete
dupa el", apelând metoda de finalizare a obiectului respectiv.. Uzual, în timpul finalizarii un obiect
îsi închide fisierele si socket-urile folosite, distruge referintele catre alte obiecte (pentru a usura
sarcina colectorului de gunoaie), etc.
De exemplu, clasa Rectangle are urmatorul cod pentru finalizarea obiectelor sale:
class Rectangle {
protected void finalize() throws Throwable {
origin = null;
super.finalize(); }}
25. Utilizarea claselor care corespund tipurilor de date primitive
Classes which correspond to primitive data types are called “wrapper classes” (clase de
ambalare/incapsulare). Wrapper classes is a class that encapsulates types, so that those types can be
used to create object instances and methods in another class that need those types.
Primitive wrapper classes are used to create an object that needs to represent primitive types in
collection classes in the java.util package and in the java.lang.reflect reflection package. Collection
classes are Java classes that can store objects in a manner similar to how data structures like arrays
store primitive data types like int, double, long or char, etc.,[2] but arrays store primitive data types
while collections actually store objects.
The primitive wrapper classes and their corresponding primitive types are:

Primitive Wrapper Constructor


type class arguments

byte Byte byte or String

short Short short or String

int Integer int or String

long Long long or String

float Float float, double or String

double Double double or String

char Character char

boolean Boolean boolean or String

The difference between wrapper classes and primitive types


Whereas variables, for example, can be declared in Java as data types double, short, int, etc., the
primitive wrapper classes create instantiated objects and methods that inherit but hide the primitive
data types.
The Byte, Short, Integer, Long, Float, and Double wrapper classes are all subclasses of the Number
class. Other wrapper classes are BigDecimal and BigInteger, but they are not primitive classes.
These classes are immutable.
Exemplu de obiect cu utilizarea clasei “wrapper” (obiect pe baza unei valoari numerice):
Integer intObject1 = new Integer(34);
26. Metode (funcții) în limbajul de programare Java, transmiterea parametrilor metodelor,
întoarcerea valorilor de către metode, variabile locale, metode recursive
O functie este o bucata de cod, sau un set de instructiuni care sunt executate doar atunci cand
respectiva functie este apelata. Pentru ca o functie sa returneze special o valoare, un rezultat se
foloseste instructiunea return. Aceasta specifica valoarea pe care o returneaza functia cand este
apelata.
public class Main {
static void myMethod() {
// code to be executed
}}
In Java transmiterea parametrilor la apelul metodelor se face numai prin valoare. Acest lucru are ca
efect faptul ca modificarile aduse parametrilor in interiorul unei functii nu se pastreaza la revenirea
din functia respectiva.

Variabile locale sunt definite pe stiva metodei si ele exista atâta timp cât metoda este executata
(exista in stiva de apeluri). Variabilele locale nu pot fi accesate si din interiorul unor metode
imbricate chiar daca ele exista cand metoda imbricata este executata.

O funcție recursivă este cea care se apeleaza de una sau de mai multe ori de catrea ea insasi. Exista
doua tipuri de metode recursive in Java:

1. Recursivitate directă
Aici funcția1 se numește continuu, deci este o funcție recursivă.

public static void main(String() args){ function() {


function(); function();
} }

2. Recursivitate indirecta/ reciprocă

O funcție1 care apelează o altă funcție2, care la rândul său apelează funcție1 se numește funcție
indirectă recursivă.
function1(){ function2(){
function2(); function1();
} }
27. Metode supraîncărcate și suprascrise
Supraîncarcarea se referă la posibilitatea de a avea într-o clasă mai multe metode cu același nume,
dar implementari diferite. În Java, compilatorul poate distinge între metode pe baza semnăturii lor,
acesta fiind mecanismul din spatele supraîncărcarii. O clasă poate supraîncărca metodele moștenite.
Constructorii pot fi supraîncărcați.

Supraîncărcarea are loc la compilare, motiv pentru care mai este numită și polimorfism static
(compile time polymorphism). În aceasta fază compilatorul decide ce metodă este apelată pe baza
tipului referinței și prin analiza numelui și a listei de parametri. La runtime, când este inițiat apelul
unei metode supraîncărcate, deja se știe unde este codul care trebuie executat.

Exemplu de supraincarcare a metodei “div”:


public class Div{
public int div(int a , int b){
return (a / b); }
public int div(int a , int b , int c){
return ((a + b ) / c); }
}

Suprascrierea se referă la redefinirea metodelor existente în clasa părinte de către clasa copil în
vederea specializării acestora. Metodele din clasa parinte nu sunt modificate. Putem suprascrie doar
metodele vizibile pe lanțul de moștenire (public, protected). O metodă din clasa copil suprascrie
metoda din clasa părinte dacă are același tip de return și aceeași semnatură (nume și parametri).

Câteva reguli pentru suprascriere sunt:


- metoda suprascrisă are același tip de return și semnatură ca metoda inițială
- specificatorul de access al metodei suprascrise nu poate fi mai restrictiv decât cel al metodei
inițiale
- metodele de tip static și final nu pot fi suprascrise
- constructorii nu pot fi suprascriși

Exemplu de suprascriere a metodei “view”:


class Parent{
void view(){
System.out.println("this is a parent class method);
}}
class Child extends Parent{
void view(){
System.out.println("this is a child class method);
}}

Parent ob1 = new Child(); Output: this is a child class


ob1.view(); method
28. Elemente statice ale clasei; specificatorul „final”
Static este un cuvânt cheie, aplicabil claselor, variabilelor, metodelor și blocurilor. Când un membru
al clasei este declarat static, acesta devine global pentru toți ceilalți membri ai clasei.

Membrul static al clasei nu ocupă memorie pe bază de instanță, adică toate obiectele au aceeași
copie a membrului static. Elementul static poate fi utilizat independent de orice obiect din acea
clasă.

Forma generală pentru a accesa membrul static al clasei: class_name.static_member

Variabile statice:

- O variabilă statică acționează ca o variabilă globală pentru toți ceilalți membri ai clasei.
- O variabilă statică poate fi accesată înainte ca orice obiect al clasei să existe.
- O variabilă statică poate fi accesată cu numele clasei în care este definită urmată de
operatorul punct (.).

Metode statice:

- O metodă statică poate apela numai alte metode statice.


- O metodă statică poate accesa numai date statice.
- O metodă statică nu poate fi referită la „acest” sau „super” în nici o condiție.
- O metodă statică poate fi accesată cu numele clasei în care este definită urmată de operatorul
punct (.).

Clasa statică

- Java are conceptul de clasă statică imbricată. Clasa cea mai exterioară nu poate fi făcută
statică, în timp ce clasa cea mai interioară poate fi făcută statică.
- O clasă imbricată static nu poate accesa membrul nestatic al clasei exterioare.
- Poate accesa numai membrii statici ai clasei exterioare.

Final este un cuvânt cheie aplicabil clasei, variabilei și metodelor. Clasa, variabila și metoda sunt
declarate ca finale folosind cuvântul cheie „final” precedat de numele lor. Odată ce o variabilă este
declarată definitivă; nu poate fi modificat în continuare în program. Variabilele finale nu ocupă
memorie pe bază de instanță.Toate obiectele claselor au aceeași copie a variabilei finale.

Exemplu: // a final variable


final int THRESHOLD = 5;
// a final static variable PI
static final double PI = 3.141592653589793;
29. Constructori ai claselor, constructori cu parametri, operatorul „this”
Intr-o clasa se pot defini metode, dar exista un tip special de metode care sunt folosite pentru a
rezolva o anumita problema, aceea de a construi obiecte. Constructori sunt metode speciale datorita
rolului lor si pentru ca au o multime de reguli privind declararea si utilizarea lor.
De fiecare data cand este creat un obiect, este apelat un constructor. Pornind de la aceasta
certitudine, în Java, fiecare clasa are cel putin un constructor , chiar daca programatorul nu a
declarat în mod explicit unul.
Daca se defineste cel putin un constructor (cu parametri) si este nevoie de cel implicit, acesta trebuie
definit in mod explicit; in caz contrar se obtine o eroare de compilare atunci cand aecsta este apelat.
public class Car{
int modelYear;
String modelName;

public Car(){ //Constructor fara parametrii


modelYear = 0;
modelName = “”;
}
public Car(int year, String name){ //Constructor cu parametrii
modelYear = year;
modelName = name;}}

Cuvântul cheie this se referă la instanța curentă a clasei și poate fi folosit de metodele, care nu sunt
statice, ale unei clase pentru a referi obiectul curent. Apelurile de funcții membru din interiorul unei
funcții aparținând aceleiași clase se fac direct prin nume. Apelul de funcții aparținând unui alt obiect
se face prefixând apelul de funcție cu numele obiectului. Situația este aceeași pentru datele membru.

Totuși, unele funcții pot trimite un parametru cu același nume ca și un câmp membru. În aceste
situații, se folosește cuvântul cheie this pentru dezambiguizare, el prefixând denumirea câmpului
când se dorește utilizarea acestuia.
În general, cuvântul cheie this este utilizat pentru:
- a se face diferenta între câmpuri ale obiectului curent și argumente care au același nume
- a pasa ca argument unei metode o referință către obiectul curent
- a facilita apelarea constructorilor din alți constructori, evitându-se astfel replicarea unor
bucăți de cod

In exemplul de mai sus variabilele se pot accesa in urmatorul mod folosind cuvantul cheie “this”:
public Car(){ //Constructor fara parametrii
this.modelYear = 0;
this.modelName = “”;
}
Astfel se evidentiaza referinta la campurile obiectului curent.
30. Moștenirea în Java, avantajele și tipurile de moștenire
Numită și derivare, moștenirea este un mecanism de refolosire a codului specific limbajelor
orientate obiect și reprezintă posibilitatea de a defini o clasă care extinde o altă clasă deja existentă.
Ideea de bază este de a prelua funcționalitatea existentă într-o clasă și de a adăuga una nouă sau de a
o modela pe cea existentă.

Moștenirea este folosită în general atunci când se dorește construirea unui tip de date care să
reprezinte o implementare specifică (o specializare oferită prin clasa derivată) a unui lucru mai
general. Un exemplu simplu ar fi clasa Dacia care moștenește clasa Car.

Clasa existentă este numită clasa-părinte, clasa de bază sau super-clasă. Clasa care extinde clasa-
părinte se numește clasa-copil (child), clasa derivată sau sub-clasă.

Sintaxa pentru moştenire este:

class NumeSubclasa extends NumeSuperclasa{


//metode
//câmpuri de instanţă
}

Avantaje:
- posibilitatea reutilizării codului ;
- obţinerea extensiei unei clase fară a fi necesară o recompilare a clasei iniţiale;
- utilizarea polimorfismului în timpul executiei programului prin folosirea funcţiilor virtuale.
Tipuri de Moştenire:
- Moştenire simplă: clasa derivată preia caracteristicile şi metodele unei singure clase de bază;
- Moştenire multiplă: clasa derivată preia caracteristicile şi metodele de la mai multe clase de
bază.
Mostenirea multipla este obtinuta prin intermediul interfetelor:

class NumeClasa implements NumeInterfata { … }


31. Operatorul „super”, cele două forme ale sale
În java cuvântul cheie super se referă la superclasa clasei în care apare super. O subclasă moștenește
variabilele și metodele accesibile din superclasa sa, dar constructorii superclasei nu sunt moșteniți în
subclasă. Ele pot fi invocate numai de la constructorii de subclasă folosind cuvântul cheie super.
Este utilizat în principal în următoarele contexte:
1. Utilizarea super cu variabile: Acest scenariu apare atunci când o clasă derivată și o clasă de bază
are aceiași membri de date. În acest caz, există o posibilitate de ambiguitate pentru JVM. O putem
înțelege mai clar folosind acest fragment de cod:
2. Utilizarea super cu metode: Aceasta este utilizată atunci când vrem să apelăm metoda clasei
părinte. Deci, ori de câte ori un părinte și un copil au aceleași metode numite, atunci pentru a rezolva
ambiguitatea, folosim super cuvânt cheie. Acest fragment de cod vă ajută să înțelegeți utilizarea
super-cuvântului cheie.

Alte puncte importante:


- Apelul la super () trebuie să fie prima declarație din constructorul clasei derivate.
- Dacă un constructor nu invocă în mod explicit un constructor de superclasă, compilatorul
Java introduce automat un apel către constructorul fără argumente al superclasei. Dacă
superclasa nu are un constructor fără argumente, veți primi o eroare în timpul compilării.
- Dacă un constructor de subclasă invocă un constructor al superclasei sale, fie explicit, fie
implicit, s-ar putea crede că un întreg lanț de constructori a apelat, până la constructorul
obiectului. De fapt, acesta este cazul.

Exemplu:
class Animal { class Dog extends Animal {
// default constructor // default constructor of
Animal(){ class Dog
System.out.println("animal"); Dog() {
} super();
} System.out.println("dog");
}
}

class Main { Output:


public static void main(String[] args){
Dog dog1 = new Dog(); animal
} dog
}
32. Clase abstracte: declararea, utilizarea, metode abstracte
Clasele abstracte sunt utilizate pentru a declara caracteristici comune unor subclase. O clasa
abstracta nu poate fi instantiata. Ea poate fi utilizata numai ca si superclasa pentru alte clase care
extind clasa abstracta. Clasele abstracte sunt declarate prin intermediul modificatorului abstract.
O clasa abstracta poate contine atribute, care descriu caracteristicile clasei, si metode, care descriu
actiunile care pot fi desfasurate de clasa. De asemenea, o clasa abstracta poate include metode care
nu sunt implementate. Aceste metode detin doar declaratie si poarta numele de metode abstracte. Ca
si in cazul claselor abstracte, metodele abstracte sunt insotite in declaratia lor de modificatorul
abstract.
Daca o clasa contine metode abstracte, atunci ea trebuie sa fie declarata abstracta.

public abstract class ObiectGrafic { … }


Toate clasele concrete derivate dintr-o clasa abstracta trebuie sa implementeze metodele abstracte
prezente in clasa de baza.

O metodă abstractă este o metodă care este declarată fără o implementare (fără acolade și urmată de
punct și virgulă), astfel:
abstract void moveTo(double deltaX, double deltaY);
33. Interfețe: declararea, utilizarea
In limbajul Java, interfetele ofera raspuns lipsei mostenirii multiple. O interfata creeaza un protocol
pe care clasele trebuie sa il implementeze. Folosind interfete, poate fi precizat pentru o clasa ce sa
implementeze, dar nu si cum sa faca acest lucru.

Interfetele reprezinta constructii Java similare claselor abstracte. Ele pot contine declaratii de
constante si metode fara implementare. Dupa definire, o interfata poate fi implementata de un numar
nedefinit de clase. De asemenea, o clasa poate implementa oricate interfete doreste.

Pentre a implementa o interfata, o clasa trebuie sa ofere implementare tuturor metodelor definite in
interiorul interfetei respective. Nu prezinta importanta modul in care metodele vor fi implementate
in clasa.

Definirea unei interfete se realizeaza in mod similar cu cea a unei clase, prin intermediul cuvantului
cheie interface.

[modificatori] interface nume_interfata [extends


lista_super_interfete] {
// declaratii metode abstracte
// declaratii constante
}

In declaratia unei interfete poate fi utilizat doar modificatorul public. Toate atributele definite in
interiorul unei interfete sunt implicit constante, chiar daca nu sunt declarate folosind modificatorii
static si final. Este obligatorie initializarea acestor atribute de tip constanta. Metodele declarate intr-
o interfata sunt implicit definite cu modificatorii abstract si public.

Un exemplu pentru o interfață care extinde mai multe interfețe:

interface A{
void a1();
void a2();
}
interface B {
int x = 0;
void b();
}
interface C extends A, B {
// this interface will expose
// * all the methods declared in A and B (a1, a2 and b)
// * all the fields declared in A and B (x)
}
34. Deosebirile și asemănările dintre clase abstracte și interfețe
În primul rând, o clasă abstractă permite câmpuri care nu sunt statice sau finale, spre deosebire de
câmpurile statice și finale utilizate în interfețe. Interfețele nu pot avea niciun cod de implementare
folosit în ele și poate exista un cod de implementare folosit în clasa abstractă. Codurile de
implementare introduse în clasa abstractă pot avea câteva sau toate metodele implementate. În mod
implicit, toate metodele interfeței sunt "abstract. „

Vizibilitatea este, de asemenea, posibilă pentru metodele sau membrii unei clase abstracte, care pot
varia, cum ar fi public, protejat, privat sau nici unul. Vizibilitatea interfeței, pe de altă parte, poate fi
presetată doar la un mod de vizibilitate care este "public". ""

O clasă abstractă va moșteni automat clasa de obiecte. Aceasta, de fapt, înseamnă că sunt incluse
metode precum clona () și egal (). Într-o interfață, nu este posibilă nicio moștenire a clasei
obiectului. După aceasta, clasa abstractă are capacitatea de a avea un constructor, dar o interfață nu
poate avea una.

Interfața din Java are de asemenea o funcție foarte importantă cu implementarea mai multor
moșteniri, deoarece o clasă poate avea doar o clasă super. Deși poate exista o singură clasă
superioară, ea poate fi implementată în orice număr de interfețe. Nu este posibil să existe mai multe
moșteniri într-o clasă abstractă.

În performanță, interfețele tind să fie mai lente în implementare, spre deosebire de clasa abstractă, în
principal datorită direcției suplimentare de găsire a metodei corespunzătoare într-o clasă. Diferența,
totuși, a devenit mai lentă datorită mașinilor virtuale moderne Java care sunt în continuă actualizare.
Adăugarea unei metode într-o interfață necesită urmărirea tuturor claselor de implementare care
implementează interfața specifică. Alternativ, se poate extinde interfața astfel încât să permită să
aibă metode suplimentare. Dacă se întâmplă să se ocupe de o clasă abstractă, tot ce este necesar este
să fie adaugata implementarea implicită a metodei și codul va continua să funcționeze. În măsura în
care există diferențe între clasele abstracte și interfețe, este important de reținut că nu sunt rivali.
35. Pachete, avantajele polimorfismului, exemple

In limbajul Java pachetele de clase reprezinta entitati logice care permit organizarea claselor si
interfetelor. Pachetele de clase sunt colectii de clase si interfete inrudite, care asigura atat controlul
accesului, cat si controlul spatiului de nume.

Pachetele de clase sunt utilizate in limbajul Java, deoarece permit:


- o mai buna organizare a aplicatiilor;
- evitarea conflictelor de nume intre clase sau interfete;
- utilizarea mult mai facila a anumitor clase si interfete;
- controlul accesului la clase si interfete.

Crearea unui pachet se realizeaza prin intermediul instructiunii package, care specifica un nume
pentru pachetul care urmeaza a fi creat. Aceasta instructiune va fi plasata in fisierele sursa care
cuprind clasele si interfetele din pachet.
Instructiunea package (declaratia de pachet) trebuie sa ocupe prima linie intr-un fisier sursa. De
asemenea, nu poate fi specificata decat o singura declaratie de pachet intr-un fisier sursa. Daca un
fisier sursa contine o instructiune package, aceasta va fi aplicata tuturor claselor si interfetelor
definite in acel fisier sursa.

Polimorfismul este capacitatea unui obiect de a lua multe forme. Cea mai obișnuită utilizare a
polimorfismului în POO apare atunci când se folosește o referință de clasă părinte pentru a se referi
la o clasă copil obiect.
Exemplu: public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}

Acum, clasa Deer este considerată polimorfă, deoarece aceasta are o moștenire multiplă.

Avantajele polimorfismului:
- Codul programatorilor poate fi reutilizat prin polimorfism;
- Suportă un singur nume de variabilă pentru mai multe tipuri de date;
- Reduce utilizarea unui obiect de către un alt obiect.
36. Utilizarea listelor, clasele „ArrayList”, „LinkedList” și altele
Lista în Java oferă facilitatea de a menține o colecția ordonata. Acesta conține metodele bazate pe
index pentru a insera, actualiza, șterge și căuta elemente. Poate avea și elementele duplicate. De
asemenea, se pot stoca elementele nule în listă.

Interfața List se găsește în pachetul java.util și moștenește interfața Collection. Clasele de


implementare ale interfeței List sunt ArrayList, LinkedList, Stack și Vector. ArrayList și LinkedList
sunt utilizate pe scară largă în programarea Java.
1. Clasa ArrayList care este implementată în cadrul de framework-ului Collection ne oferă
listele dinamice în Java. Deși, poate fi mai lent decât listele standard, poate fi util în
programele în care este nevoie de o mulțime de manipulări in lista.
// Creating a list
List<Integer> l1 = new ArrayList<Integer>();
// Adds 1 at 0 index
l1.add(0, 1);
// Remove the element from position 0
l1.remove(0);

2. LinkedList este o structură de date liniară în care elementele nu sunt stocate în locații
adiacente și fiecare element este un obiect separat cu o parte de date și o parte de adresă.
Elementele sunt legate folosind pointeri și adrese. Fiecare element este cunoscut sub numele
de nod.
// Declaring the List with initial size n
List<Integer> ll = new LinkedList<Integer>();

3. Vectorul implementează o matrice dinamică care înseamnă că poate crește sau micșora după
cum este necesar. La fel ca o matrice, conține componente care pot fi accesate folosind un
index întreg.
// Declaring the List with initial size n
List<Integer> v = new Vector<Integer>(n);

// Appending the new elements


// at the end of the list
for (int i = 1; i <= n; i++)
v.add(i);
// Printing elements one by one
for (int i = 0; i < v.size(); i++)
System.out.print(v.get(i) + " ");

// Remove element at index 3


v.remove(3);
37. Colecții, mulțimi, dicționare, clasele „HashSet”, „TreeSet” și altele

O colectie este de fapt un obiect care grupeaza mai multe elemente intr-o singura unitatae. Colectiile
se utilizeaza pentru stocarea, regasirea si manupularea datelor. Deci colectiile reprezinta obiecte care
in mod natiral formeaza un grup.

Dicționarul în Java este o clasă abstractă în Java care stochează datele sub formă de perechi cheie-
valoare si se găsește în pachetul java.util. Fiecare cheie are o valoare și putem prelua valorile într-un
obiect Dicționar folosind cheia corespunzătoare.
Putem declara un obiect de dicționar în Java în modul de mai jos:

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


Adaugarea datelor intr-un dictionar se realizeaza folosind metoda put()
map.put("dog", "type of animal");

Pentru interfata Set sunt disponibile si urmatoarele doua implementari standard:


• HashSet: este utilizata pentru o implementare rapida, care nu stabileste o ordonare a elementelor;
elementele sunt memorate intr-o tabela de dispersie (hash table);
import java.util.HashSet; // Import the HashSet class
HashSet<String> cars = new HashSet<String>();

• TreeSet: ofera acces ordonat la elementele multimii, acestea fiind ordonate ascendent pe baza
valorilor; elementele sunt memorate sub forma unui arbore binar; implementarea este mai lenta
decat in cazul lui HashSet.
Set<String> ts1 = new TreeSet<>();
In ambele cazuri adaugarea datelor se realizeaza folosind metoda add():
cars.add("Volvo");
ts1.add(“Val”);
38. Lucrul cu comparatorul colecțiilor
Să presupunem că avem un Array / ArrayList de propriul nostru tip de clasă, care conține câmpuri
precum numar, nume, adresă, etc. și trebuie să sortăm lista pe baza numarului sau numelui.
Metoda 1: O abordare evidentă este să scriem propria noastră funcție sort () folosind unul dintre
algoritmii standard. Această soluție necesită rescrierea întregului cod de sortare pentru diferite
criterii, cum ar fi numărul ruloului și numele.

Metoda 2: Utilizarea interfeței de comparare - Interfața de comparare este utilizată pentru a compara
obiectele unei clase definite de utilizator. Această interfață este prezentă în pachetul java.util și
conține 2 metode compare(Object obj1, Object obj2) și equals(Object element). Folosind un
comparator, putem sorta elementele pe baza membrilor datei.
class Student { … }
class Sortbyname implements Comparator<Student> {
// Used for sorting in ascending order of name
public int compare(Student a, Student b)
{
return a.name.compareTo(b.name);
}
}
// Driver class
class Main {
public static void main(String[] args)
{
ArrayList<Student> ar = new ArrayList<Student>();
ar.add(new Student(111, "bbbb", "london"));
ar.add(new Student(131, "aaaa", "nyc"));

Collections.sort(ar, new Sortbyname());


}
}
Modificând valoarea de returnare din cadrul metodei de comparare, se poate sorta în orice ordine
crescatoare sau descrescatoare. De exemplu. pentru ordine descrescătoare, trebuie schimbate doar
pozițiile „a” și „b” în metoda de comparare de mai sus.
39. Lucrul cu fișierele, utilizarea serializării
Fluxurile Java pun la dispozitie modalitatea prin care o aplicatie permite citirea unor informatii
care se gasesc pe o sursa externa, respectiv trimiterea unor informatii catre o destinatie externa.
Informatia se poate gasi oriunde : într-un fisier pe disc, în retea, în memorie sau în alt program.
Mai mult, prin fisiere este posibila comunicarea între doua sau mai multe fire de executie ale
aceleiasi aplicatii.
Urmatoarele metode care se regasesc ca functii membre ale tuturor claselor ce implementeaza
fluxurile de intrare :
- read() - citeste date dintr-un flux de intrare
- skip() - ignora unele date din fluxul de intrare
- markAvailable() - testeaza daca metoda mark() este disponibila pentru fluxul de intrare
Metode pentru fluxurile de iesire
- write() - scrie date într-un flux de iesire
- flush() - forteaza scrierea datelor într-un canal de redirectare
- close() - închide un flux de iesire
import java.io.File; //Import the File class
File myObj= new File("filename.txt");//Specify the filename
myObj.write("Acest text a fost adaugat in fisier!")

Utilizand fluxurile putem scrie aplicatii care salveaza si incarca datele in fisiere. Java permite si un
mecanism mai avansat si anume serializarea obiectelor. In forma cea mai simpla serializarea
obiectelor inseamna salvarea si restaurarea starii obiectelor. Obiectele oricarei clase care
implementeaza interfata Serializable, pot fi salvate intr-un stream(fluxde date) si restaurate din
acesta.
Utilizand serializarea putem salva obictele create pe o platforma si le putem transmite prin retea pe
un alt calculator care nu trebuie neaparat sa se ruleze pe aceasi platforma, totusi permite restauraea
corecta a obiectelor.
Pentru a putea fi serializat un obiect trebuie sa fie instanta a unei clase care implementeaza una din
interfetele :

java.io.Serializable sau
java.io.Externalizable (care extinde clasa Serializable)

Salvarea unui obiect intr-un fisier se realizeaza astfel :

MyObject o = new MyObject();


FileOutputStream fout = new FileOutputStream(“fisier”);
ObjectOutputStream sout = new ObjectOutputStream(fout);
sout.writeObject(o);
40. Lucrul cu datele calendaristice, clasele „Calendar” și Gregorian Calendar”
Java oferă clasa Date disponibilă în pachetul java.util, această clasă încapsulează data și ora curente.
import java.util.Date;
public class DateDemo {

public static void main(String args[]) {


// Instantiate a Date object
Date date = new Date();

// display time and date using toString()


System.out.println(date.toString());
}
}
Output: May 25 09:51:52 CDT 2021

GregorianCalendar este o subclasă concretă (una care are implementarea tuturor membrilor săi
moșteniți fie din interfață, fie din clasa abstractă) a unui calendar.
Diferența majoră între clasele GregorianCalendar și Calendar este că clasa Calendar fiind o clasă
abstractă nu poate fi instanțiată. Deci, un obiect al clasei Calendar este inițializat ca:
Calendar cal = Calendar.getInstance();
Aici, un obiect numit cal din clasa Calendar este inițializat cu data și ora curente din setările locale și
fusul orar implicit. În timp ce, Clasa GregorianCalendar fiind o clasă concretă, poate fi instanțiată.
Deci, un obiect al clasei GregorianCalendar este inițializat ca:
GregorianCalendar gcal = new GregorianCalendar();
41. Noțiunea de excepție, tipuri de excepții, prelucrarea excepțiilor (instrucțiunile „try”, „catch”
și „finally”)
In limbajul Java exceptiile ofera un mecanism eficient de identificare si rezolvare a erorilor.
Exceptiile reprezinta situatii care apar in timpul executiei unui program si care determina oprirea
acestuia. Java ofera posibilitatea tratarii exceptiilor prin stabilirea unei cai alternative de continuare a
executiei programului.
De exemplu, pot fi generate exceptii in urmatoarele cazuri:
- realizarea unei impartiri la zero ArithmeticException;
- deschiderea unui fisier care nu exista FileNotFoundException;
- accesarea indexului unui tablou care depaseste limitele IndexOutOfBoundsException;
- utilizarea unui atribut care nu a fost definit NoSuchFieldException.
La aparitia unei exceptii este generat automat un obiect care contine toata informatia
corespunzatoare exceptiei.

Java ofera o solutie eficienta de rezolvare a exceptiilor care apar intr-un program prin intermediul
mecanismului de tratare a exceptiilor. Implementarea unei astfel de solutii se face folosind
constructii de genul try … catch … finally.

Sintaxa generala pentru o instructiune try … catch … finally este urmatoarea:

try {
// instructiuni supravegheate
}
catch (Exceptie1 e1) {
// tratare exceptie e1 de tip Exceptie1
}
catch (Exceptie2 e2) {
// tratare exceptie e2 de tip Exceptie2
}
finally {
// instructiuni care se executa neconditionat
}
42. Generarea excepțiilor proprii, instrucțiunea „throw” și „throws”
Generarea unei exceptii poate fi realizata prin intermediul instructiunii throw, astfel:

throw obiect_exceptie;
Putem considera ca exceptiile reprezinta al doilea tip returnat de catre o metoda. Din acest motiv, o
metoda trebuie sa declare tipurile de exceptii care pot fi lansate din interiorul ei. In caz contrar,
compilatorul Java genereaza o eroare de compilare.

Declararea tipurilor de exceptii care pot aparea intr-o metoda este realizata folosind cuvantul cheie
throws in declaratia metodei.

[modificatori] tip_metoda nume_metoda( [lista parametrii] )


[throws tip_exceptie1, ... ] {
// corp metoda
}

Exceptiile declarate in antetul unei metode extind clasa Exception si cuprind conditii de eroare care
apar datorita problemelor de comunicatie cu sisteme externe sau datorita lucrului cu intrarile. Aceste
conditii de eroare trebuie tratate dinamic, deoarece ele nu pot fi prevenite.

S-ar putea să vă placă și