Sunteți pe pagina 1din 60

Limbajul Java - 20 de lecții

1. Lecția 01
2. Lecția 02
3. Lecția 03
4. Lecția 04
5. Lecția 05
6. Lecția 06
7.
Java - Lecția 01
DE MIHAI SCORȚARU · 10 MAI 2015
Începem acum cu adevărat seria de articole dedicate prezentării fundamentelor
programării. Acesta este primul articol din versiunea Java a seriei. Dacă vă uitați la
articolele corespunzătoare din versiunile dedicate celorlalte limbaje, veți observa că
sunt foarte asemănătoare. Vă rugăm să nu ne acuzați de copy & paste… Există un
motiv întemeiat! Vrem să fie asemănătoare. Vrem să arătăm elementele comune ale
limbajelor. Nu are rost să reformulăm doar de dragul de a prezenta lucrurile puțin
diferit.

De ce Java?
Motivul principal pentru care Java este unul dintre limbajele alese este acela că
limbajul este, în momentul scrierii articolului, cel mai folosit în industria software.
Nu este un prim loc detașat și probabil nu va rămâne în frunte pentru totdeauna.
Totuși, credem că va avea o viață destul de lungă și cunoașterea sa este utilă.

După un start care va părea mai dificil comparativ cu alte limbaje, veți vedea că
lucrurile devin din ce în ce mai simple. Se spune că în Java lucrurile funcționează
de la sine, totul este intuitiv și șansele de a greși sunt mai mici. Va trebui să aveți
puțină răbdare. Elementele de bază prezentate în cadrul acestui prim articol vor
părea exagerat de complicate. Din fericire, trebuie să știți doar că se poate face, că
așa se face și nu de ce trebuie scris atât de mult cod.

Datorită faptului că este utilizat de atât de mulți programatori, multe lucruri au fost
deja făcute de alții și limbajul de permite foarte ușor să folosim codul scris de alții.

Există o mulțime de tehnologii care utilizează limbajul Java. Folosind acest limbaj


vom putea dezvolta aplicații software dintre cele mai diverse. Vom scrie programe
care vor rula pe servere, pe calculatoarele obișnuite, pe tablete, pe telefoane sau pe
diversele dispozitive portabile care sunt lansate acum pe piață. Deși este posibilă
utilizarea altor limbaje, cam tot ce are legătură cu sistemul de operare Android de
la Google va fi scris, în principiu, în Java.

Mediul de programare
Există două medii de programare preferate în comunitatea Java: Eclipse și IntelliJ
IDEA. Fiecare are avantajele sale, pe măsură ce apar versiuni noi fiecare încearcă
să adauge facilități noi, dar și facilitățile deja oferite de celălalt. Chiar și în redacția
Gazetei de Informatică părerile sunt împărțite. La un moment dat va trebui să
alegeți unul dintre ele (sau altul dacă vă place mai mult, dar șansele sunt relativ
mici). Ambele sunt disponibile pentru diverse sisteme de operare și sunt relativ
ușor de instalat. Dar, instalarea acestor medii de programare depășește scopul
acestui articol. Dacă știți folosi un mediu de programare (sau vă ajută cineva), o
puteți face. Pentru a ne păstra neutralitatea, vom oferi o soluție alternativă care nu
necesită instalare.
Pe parcursul acestei serii de articole, exemplele vor fi create și rulate folosit un
mediu de programare disponibil online. Sunt mai multe disponibile, așa că vom
alege la întâmplare. Nu avem criterii clare după care să alegem așa că Google a ales
în locul nostru. O căutare după java environment online ne-a dus
la http://ideone.com/. E suficient de bun deocamdată. Dacă aveți motive să credeți
că ar fi trebuit să alegem altceva, vă rugăm să ne atenționați…

Să începem…
Dacă accesați site-ul veți ajunge la o pagină care arată cam așa (am eliminat
elementele neesențiale):

Observați că avem deja un program scris. Acesta este un fel de program minimal
în Java. Nu face nimic. Nu trebuie să înțelegeți acum ce rol au toate acele texte…
Puteți apăsa butonul Run din dreapta jos și se va executa. Veți ajunge în situația
din imaginea de mai jos.
Observăm că execuția s-a încheiat cu succes, dar în rest nu s-a întâmplat mare
lucru. Totuși, vedem că adresa paginii afișate s-a modificat (în cazul nostru
este http://ideone.com/gF0qHX, dar programul fiecăruia va fi disponibil la o altă
adresă). Vom putea întotdeauna accesa programele scrise folosind aceste adrese.
Dacă dorim să facem ceva, ar trebui totuși să modificăm acest program care nu face
nimic. Pentru aceasta putem apăsa butonul edit din stânga-sus. Adresa nu se mai
modifică, dar acum putem efectua modificări în program.
Să înlocuim // your code goes here cu // aici trebuie scris
codul. Din motive cunoscute doar de creatorii site-ului, în locul
butonului Run avem un buton numit Ideone it! Apăsându-l vom rula noul program
care, poate v-ați așteptat, nu va face nici el nimic. Pentru a ne păstra modificările va
trebui să apăsăm butonul Save.

Primul program adevărat


Tradiția spune că primul program scris într-un limbaj de programare nou este cel
care tipărește mesajul Hello World! Noi vom fi mai originali și vom tipări Gazeta
de Informatică.
Așa cum probabil vă imaginați, codul va fi scris în zona în care ne-am “jucat”.
Vom înlocui textul // aici trebuie scris codul cu o
comandă Java propriu zisă, vom salva și vom rula programul. Comanda respectivă
este cea din articolul introductiv:

1 System.out.println("Gazeta de Informatică");

După rulare, veți observa că în zona din partea inferioară a ecranului a apărut textul
dorit.
 

Tocmai am realizat una dintre operațiile fundamentale efectuate de programele de


calculator. Am oferit o informație în exterior. De data aceasta am scris ceva pe
ecran. Programele comunică rezultatele executării lor furnizând așa numitele date
de ieșire. Acestea pot lua diverse forme. Cea mai simplă este tipărirea unui simplu
text, dar sunt multe altele cum ar fi tipărirea la o imprimantă, desene sau filme pe
ecran, sunete în boxe etc., dar și informații codificate care nu pot fi înțelese decât
de alte programe.

Date de intrare
Programele ne furnizează date de ieșire. De cele mai multe ori ele au nevoie de
informații din exterior. Acestea le sunt comunicate prin intermediul așa numitelor
date de intrare. Dacă prin intermediul datele de ieșire programele ne furnizează
informații, prin intermediul datelor de intrare noi suntem cei care oferim informații.
Și datele de intrare pot lua diverse forme: informații introduse de la tastatură,
mișcarea mouse-ului, apăsarea butoanelor mouse-ului, apăsarea unui touchscreen,
rostirea în microfon, etc. Poate vă imaginați că acele informații codificate pe care le
menționam la sfârșitul secțiunii anterioare, cele care nu pot fi înțelese decât de alte
programe, reprezintă date de intrare pentru aceste alte programe.

Dar, să ne concentrăm asupra unui exemplu simplu. Vom cere numele utilizatorului
și îl vom saluta. Utilizatorul își va introduce numele și după aceea va apărea
mesajul Salut, urmat de nume și de un semn de exclamare. Ca să arate totul bine,
vom adăuga și un spațiu înaintea numelui. De exemplu, dacă utilizatorul ar
introduce numele GInfo, mesajul ar fi Salut GInfo!.
Vi se părea complicată comanda prin care era afișat un text. Să vedeți acum…

1 String nume = new Scanner(System.in).nextLine();


Site-ul ne permite să specificăm date de intrare sub forma unor text înainte de a rula
programul. Acestea trebuie introduse în caseta din partea inferioară:
Dacă rulăm programul, observăm că este afișat mesajul ales.
În episoadele următoare veți înțelege ce este acel String, ce este acel nume și,
mult mai încolo, ce este un Scanner…
Deocamdată, singura observație demnă a fi luată în considerare este aceea că, în
Java, fiecare instrucțiune se încheie cu semnul punct și virgulă.

Va urma
În episodul următor vom vedea cum lucrăm cu numere și texte. Veți înțelege puțin
mai mult din programul pe care l-am folosit ca model în cadrul acestui episod.

 
Java - Lecția 02
DE MIHAI SCORȚARU · 11 MAI 2015
În cadrul acestui episod vom introduce noțiunile de variabilă și tip de date și vom
lucra cu numere și texte. Vom presupune că deja știți să utilizați un mediu de
programare (fie el și online); dacă nu, vă recomandăm să citiți din nou episodul
anterior.

Variabile
Chiar și pentru cele mai simple programe, la un moment dat avem nevoie să
păstrăm anumite informații. Nu am avut nevoie de acest lucru atunci când doar am
afișat un mesaj, dar atunci când am avut nevoie de numele utilizatorului a trebuit să
păstrăm informația respectivă. Să ne amintim ultimul program de data trecută:

1 /* package whatever; // don't place package name! */


2
3 import java.util.*;
4 import java.lang.*;
5 import java.io.*;
6
7 /* Name of the class has to be "Main" only if the class is public. */
8 class Ideone
9 {
10   public static void main (String[] args) throws java.lang.Exception
11   {
12     String nume = new Scanner(System.in).nextLine();
13     System.out.println("Salut " + nume + "!");
14   }
15 }
În linia 12, avem o instrucțiune prin care preluăm informația introdusă de utilizator
și o păstrăm în ceva de numit nume. Aceasta este o așa numită variabilă.
Variabilele pot fi văzute ca fiind niște recipiente care păstrează informații. Practic,
cu ajutorul lor ajungem undeva în memoria calculatorului, luăm o mică parte din ea
și îi dăm o denumire pentru a o putea folosi ulterior.

Avem nevoie de variabile pentru cele mai diverse scopuri. Dacă scriem un program
care controlează un roboțel, vom avea nevoie de variabile care să conțină poziția
acestuia, orientarea sa etc. În schimb, dacă programul nostru simulează un joc de
fotbal, am avea nevoie de variabile pentru a păstra scorul.
În principiu, dacă trebuie să ținem minte ceva, cel mai simplu este să punem acel
ceva într-o variabilă.

Majoritatea limbajelor moderne necesită declararea unei variabile înainte ca aceasta


să poată fi utilizată. Java este un astfel de limbaj. Mai mult, limbajul Java ne obligă
să specificăm și ce tip de variabilă dorim.
Dacă revenim la linia 12 a programului nostru, observăm că înaintea
denumirii nume, apare cuvântul String. Acesta este tipul variabilei nume. Vom
vedea exact ce înseamnă puțin mai încolo.
În Java, pentru a declara o variabilă, trebuie să precizăm tipul acesteia, urmat de
denumirea sa. Pentru un meci de fotbal, am putea avea o variabilă declarată astfel:

1 int goluriGazde;
Tipul este int (vom vedea ce înseamnă), iar denumirea este goluriGazde (vom
vedea și de ce denumirea arată oarecum ciudat). Urmează semnul ;, cel care separă
instrucțiunile în Java. Deci, declararea unei variabile este o instrucțiune.
Termenul variabilă implică faptul că ea se poate modifica. Prin diverse mecanisme,
informația conținută de o variabilă se poate schimba în timpul execuției
programului. De exemplu, într-un joc de fotbal, la începutul unui meci variabila
care ar păstra numărul golurilor marcate de echipa gazdă ar conține informația 0.
Dar, dacă echipa marchează un gol, informația respectivă trebuie să devină 1. Dacă
se mai marchează unul, variabila va conține informația 2 și așa mai departe. Dar,
dacă începe un joc nou, informația redevine 0. Această informație păstrată de către
variabilă poartă denumirea de valoare a variabilei.
În Java, este posibil ca în momentul declarării unei variabile să precizăm și ce
valoare dorim să aibă la început. Pentru aceasta, după denumirea ei (înainte de ;)
adăugăm semnul =, urmat de valoarea dorită. O astfel de declarație ar putea fi:

1 int goluriGazde = 0;
Spunem că o astfel de variabilă este inițializată.
Tipuri
Am spus că în Java variabilele au tipuri. Tipul unei variabile indică ce fel de
informație poate conține variabila respectivă. În exemplul nostru tipul este int; el
arată că variabila noastră este un număr întreg. Dacă o variabilă are un anumit tip,
atunci informația conținută trebuie să fie compatibilă cu acel tip. Putem scrie:

1 int goluriGazde = 2457;


Chiar dacă este puțin probabil să găsim vreun sport în care o echipă să
marcheze 2457 de goluri, instrucțiunea este corectă fiindcă, din punctul de vedere
al calculatorului, goluriGazde este un număr întreg și valoarea sa poate fi orice
număr întreg acceptabil (vom vedea mai încolo că există anumite restricții).
Totuși, nu putem scrie:

1 int goluriGazde = "GInfo";


GInfo este în acest caz un text (vom vedea puțin mai târziu rolul ghilimelelor) și
variabila goluriGazde nu poate conține decât numere întregi.
Variabilele pot avea diverse tipuri: ele pot fi numere întregi, numere cu zecimale
(acestea sunt denumite uneori numere reale, dar nu e chiar corect), texte etc. Dar
putem avea și tipuri mult mai complexe; putem avea variabile care reprezintă
clădiri, animale, galaxii, atomi și așa mai departe.

Unele tipuri sunt disponibile direct, altele trebuie inventate. Cele disponibile pot fi
utilizate imediat; cele create deja de alții pot fi și ele utilizate. Dar, tipurile noi
trebuie întâi definite.

În Java, tipurile disponibile imediat poartă denumirea de primitive. Acestea


sunt byte, short, int, long, float, double, char și boolean. Primele
patru pot conține numere întregi (vom vedea de ce sunt mai multe), următoarele
două pot conține numere cu zecimale, următorul un așa numit caracter, iar ultimul
doar o valoare de adevăr (adevărat sau fals).
Iată câteva exemple de declarații (împreună cu inițializările):

1 int a = 5;
2 double b = 5.1;
3 char c = '+';
4 boolean d = true;
Avem așadar un număr întreg a care are deocamdată valoarea 5, un număr cu
zecimale b care are valoarea 5.1, un caracter c care are valoarea + și un așa numit
boolean d cu valoarea true (adevărat), valorile booleene trebuie scrise în engleză și
pot fi true sau false.
Mai avem un tip special, aproape primitiv din anumite puncte de vedere,
numit String. Variabilele String conțin șiruri de caractere (mai multe
caractere într-o anumită ordine).
De obicei, string-urile conțin texte, iar caracterele sunt litere, cifre, semne de
punctuație etc. Vom vedea în viitor că aceste caractere pot reprezenta și alte lucruri,
dar deocamdată să considerăm string-urile ca fiind texte.

Un exemplu pentru declararea și inițializarea unei variabile de tip String ar fi:

1 String s = "GInfo";
Despre tipurile mai complicate vom discuta cu altă ocazie.

Numere
Am spus că în Java există mai multe feluri de numere și chiar mai multe feluri de
numere întregi. Știm că avem o infinitate de numere întregi. Pentru numere foarte
mari, noi am nevoie să scriem multe cifre; la fel, calculatoarele ar avea nevoie să
folosească tot mai multă memorie pe măsură ce numerele sunt mai mari. Dar,
memoria calculatoarelor este finită. Diferitele variante de numere întregi ne spun
cam câtă memorie dorim să utilizăm. Din acest motiv, pentru fiecare tip vom putea
avea valori care nu depășesc o valoare maximă, specifică tipului. Semnul unui
număr întreg e și el în memorie, deci putem avea și numere negative. Dar, datorită
memoriei limitate, numerele trebuie să fie mai mari decât o valoare minimă
specifică tipului.
Pare complicat și ciudat, dar nu e chiar așa. În practică nu utilizăm numere foarte
mari. În cele mai multe situații este suficient tipul int (valoarea maximă este 2  - 31

1, adică două miliarde și ceva). Uneori nu este suficient și avem nevoie de long.
Valoarea maximă este 2  - 1, adică aproape zece miliarde de miliarde. Dacă avem
63

nevoie de valori și mai mari e mai complicat, dar sunt soluții.


Am văzut cum declarăm o variabilă și cum o inițializăm. Dar, am spus că valorile
variabilelor se pot modifica. Pentru aceasta avem nevoie de o instrucțiune. O astfel
de instrucțiune arată așa:

1 a = 2457;
Valoarea variabilei a va fi acum 2457 indiferent care a fost înainte. Informația
înlocuită se pierde. Nu vom ști cât a fost acea valoare înainte, deci dacă avem
nevoie de ea, ar fi fost bine să o punem altundeva (într-o altă variabilă de exemplu).
Instrucțiunea anterioară este validă numai dacă a este într-adevăr o variabilă de tip
numeric. Ea trebuie să fi fost declarată anterior (nu neapărat și inițializată).

Să nu credeți că a = 2457; este o ecuație sau ceva asemănător; este o comandă.


Calculatorului i se spune ca în zona de memorie corespunzătoare variabilei a să fie
pusă valoarea 2457. O astfel de comandă se numește atribuire.
Printr-o instrucțiune de atribuire, unei variabile i se dă o valoare. Tipul acestei
valori trebuie să fie compatibil cu cel al variabilei (vom vedea ulterior de ce, în
unele cazuri, e posibil ca tipurile să nu fie chiar identice).

Așadar, o instrucțiune de atribuire conține denumirea variabilei care va primi


valoarea, urmată se semnul = și apoi de valoarea propriu zisă. În cazul nostru,
valoarea a fost numărul 2457.
Există mai multe modalități de a reprezenta numerele; 2457 este varianta care ni se
pare nouă naturală; nu e nicio șmecherie, e chiar numărul care urmează
după 2456 și e înainte de 2458. Fără să explicăm de ce și doar pentru a arăta că se
poate și altfel dacă chiar vrem, același număr poate fi reprezentat prin 0x999.
Instrucțiunea următoare are exact același efect:
1 a = 0x999;
În Java, numerele sunt numere simple dacă nu apare nimic altceva lipit de ele. Alte
simboluri sau caractere le modifică semnificația. Partea 999 din 0x999 nu
reprezintă deloc numărul 999; ne-am aștepta ca 02457 și 2457 să reprezinte
același lucru, dar nu e așa.
Lucrurile pot deveni și mai ciudate: 2, '2' și "2" sunt complet diferite. Primul
este numărul 2, al doilea este un caracter care reprezintă cifra 2 și al treilea este un
string. Mai multe despre caractere și string-uri în secțiunea următoare.
Numerele cu zecimale pot și ele fi reprezentate așa cum ni se pare nouă
natural; 2.5 este o valoare corectă; dar, putem avea și ciudățenii ca 1e-4 sau 5D.
Nu dorim să explicăm aceste lucruri care par bizare; dorim doar să atragem atenția
că în multe cazuri lucrurile nu sunt ceea ce par.

Caractere și string-uri
În Java un caracter reprezintă un simbol. Poate fi o literă, o cifră, un semn de
punctuație, un operator matematic etc. În Java valoarea unui caracter este cuprinsă
între apostroafe. În principiu, avem un apostrof, un semn și apoi un alt apostrof. De
exemplu, caracterul + trebuie scris '+'.
Dar, ce ne facem dacă vrem să avem chiar valoarea apostrof? Ați putea crede
că ''' este soluția, dar nu e chiar așa. Al doilea apostrof este interpretat ca fiind
sfârșitul elementelor care descriu caracterul și al treilea nu mai este înțeles. Ca
urmare, instrucțiunea c = '''; nu este corectă.
Ni se oferă o soluție… Putem marca al doilea apostrof cu un simbol special care să
indice faptul că acesta nu trebuie interpretat ca sfârșit al descrierii caracterului, ci ca
semn propriu-zis. Elementul special este \ (backslash). Varianta corectă a
instrucțiunii este:

1 c = '\'';
Ar părea că ni s-au rezolvat toate problemele, dar… dacă avem nevoie fix
de backslash? c = '\'; nu e corect fiindcă backslash-ul indică faptul că
următorul element trebuie interpretat ca fiind semnul apostrof. Soluți este să
marcăm semnul backslash cu un alt backslash. Deci, pentru a atribui unei variabile
valoarea \, va trebui să scriem:

1 c = '\\';
String-urile sunt cuprinse între ghilimele. Ați ghicit probabil, dacă unul dintre
caracterele string-ului este chiar ", avem o problemă. Probabil intuiți soluția, vom
marca astfel de caractere cu backslash. Dispare problema cu apostroful (nu mai
trebuie marcat) și este în continuare prezentă cea cu backslash-ul (trebuie și aici
dublat).
Dar… avem probleme suplimentare. Spuneam că string-urile sunt folosite în
special pentru a păstra valori care reprezintă texte. Și textele pot avea mai multe
linii. Cum facem?

Dacă scriem:

1 s = "Gazeta
2 de
3 Informatică";
vom vedea că nu e corect.

Avem conceptul de caracter special de sfârșit de linie. Dacă dorim să avem


textul Gazeta de Informatică scris pe trei rânduri (câte un cuvânt pe o linie), vom
scrie:

1 s = "Gazeta\nde\nInformatică";
Va urma
În cadrul episodului următor vom prezenta detalii referitoare la modul în care sunt
efectuate operațiile (nu neapărat matematice) și vom vedea ce sunt și la ce sunt
folosite comentariile.
Java - Lecția 03
DE MIHAI SCORȚARU · 18 MAI 2015
Cel de-al treilea episod al serialului dedicat fundamentelor programării va prezenta
detalii legate de modul în care sunt executate diverse operații. De asemenea, vom
vedea cum putrem adăuga informații suplimentare care nu afectează deloc modul în
care sunt executate programele, dar ajută la înțelegerea acestora.

Altfel de atribuiri
În cadrul episodului anterior am văzut cum putem modifica valoarea unei variabile
cu ajutorul instrucțiunii de atribuire. Dar, toate atribuirile pe care le-am prezentat
nu făceau decât să dea unei variabile o simplă valoare.

Limbajele ne permit mult mai mult. De exemplu, am putea să atribuim unei


variabile valoarea altei variabile. Să considerăm următoarea secvență:

1 int a;
2 int b;
3 a = 3;
4 b = a;
În urma executării acestor instrucțiuni, atât variabila a, cât și variabila b, vor avea
valoarea 3. Instrucțiunea din linia 4 indică faptul că variabilei b trebuie să i se
atribuie valoarea variabilei a. Cele două variabile sunt în continuare independente.
Dacă am continua programul cu a = 5; doar valoarea variabilei a se va modifica;
valoarea variabilei b va rămâne 3.
Să facem acum un mic exercițiu. Să presupunem că avem două variabile a și b care
conțin două valori diferite (pentru exemplul nostru vom considera că acestea
sunt 2 și 4). Dorim să scriem un program care schimbă între ele cele două valori.
Cele două variabile vor fi declarate și inițializate astfel:
1 int a = 2;
2 int b = 4;
Evident, pentru a rezolva problema, am putea scrie:

1 a = 4;
2 b = 2;
Dar, să ne închipuim că dorim ca programul să funcționeze corect indiferent care
sunt valorile inițiale (de exemplu, am putea presupune că ele sunt introduse de
utilizator și în momentul scrierii programului nu știm care vor fi.

Având în vedere că tocmai am prezentat cum unei variabile i se poate stribui


valoarea altei variabile, ne-am putea gândi la o soluție de genul:

1 a = b;
2 b = a;
Dar, să vedem ceva ce se întâmplă; inițial a are valoare 2 și b are valoarea 4. Prin
instrucțiunea a = b; variabilei a i se stribuie valoarea curentă a variabilei b,
adică 4. Așa cum am spus în cadrul episodului anterior, valoarea 2 se pierde. Cea
de-a doua instrucțiune face ca variabilei b să i se atribuie valoarea variabilei a; dar
această valoare este acum 4, deci în urma executării instrucțiunii, valoarea
variabilei b va fi tot 4. Astfel, ajungem să avem aceeași valoare pentru ambele
variabile și nu am schimbat valorile între ele.
Am spus că variabilele pot fi privite ca fiind niște recipiente. Să ne imaginem că
cele două variabile ar fi două pahare pline cu lichide diferite și dorim să schimbăm
lichidele între ele. Pentru a putea muta lichidul dintr-un pahar în altul, va trebui să
vărsăm lichidul dintr-un pahar pentru a face loc. În principiu, lichidul se pierde în
acest mod. Dar, l-am putea vărsa într-un al treilea pahar, nu?

Atunci, pentru a schimba lichidele între ele, vom lua un al treilea pahar, vom turna
în el lichidul din primul pahar, apoi vom turna în primul pahar lichidul din al doilea
și, la final, vom turna în al doilea pahar lichidul din cel de-al treilea. Astfel, în
primul pahar vom avea lichidul care a fost inițial în al doilea, iar în al doilea pahar
vom avea lichidul care a fost inițial în primul.

Ne dăm seama destul de ușor că pentru a schimba valorile a două variabile, avem
nevoie de o a treia variabilă (ajutătoare). Secvența care schimbă valorile ar putea fi:

1 int c = a;
2 a = b;
3 b = c;
Am declarat variabila c și am și inițializat-o. După cum se vede și la inițializare e la
fel ca la atribuire, Putem inițializa o variabilă cu valoarea altei variabile.

Prima operație
Totuși, până acum doar am declarat variabile, le-am dat valori și ne-am jucat puțin
cu ele. Dar, lucrăm cu un calculator; la un moment dat ar trebui să facem și niște
calcule, nu? Deși pare că e cam târziu fiindcă suntem deja la al treilea episod, vom
realiza acum prima adunare. Presupunem că două variabile au anumite valori pe
care dorim să le adunăm și să păstrăm rezultatul într-o a treia variabilă. Nu e nicio
mare filosofie, codul arată cam cum v-ați aștepta;

1 int a;
2 int b;
3 int c;
4 a = 2;
5 b = 4;
6 c = a + b;
Nu e nicio surpriză, valoarea variabilei c va fi 6. Dar, vedem că am atribuit
variabilei c altceva, nu o simplă valoare și nici valoarea unei alte variabile. Am
cerut efectuarea unui calcul, a unei operații; descrierea acestei operații poartă
denumirea de expresie. De fapt, și anterior am folosit tot expresii, dar foarte simple.
Valoarea simplă este și ea o expresie, la fel și valoarea unei variabile.
Așa cum putem atribui unei variabile o expresie, la fel putem și inițializa o
variabilă cu o expresie. Codul de mai jos are același efect ca cel anterior:

1 int a = 2;
2 int b = 4;
3 int c = a + b;

Expresii
Expresille pot fi foarte complexe. Ele pot conține valori simple, valori ale unor
variabile, operatori și multe altele. De exemplu, putem aduna trei numere, dintre
care doar două sunt păstrate în variabile, iar al treilea este o valoare simplă:

1 int a = 2;
2 int b = 4;
3 int c = a + b + 1;
Așa cum vă așteptați, putem realiza și alte operații matematice. Pentru scăderi și
înmulțiri nu avem nicio surpriza. La împărțire lucrurile sunt mai complicate și vom
reveni.

Pentru înmulțire, operatorul folosit este *; putem efectua o înmulțire astfel:

1 int a = 2;
2 int b = 4;
3 int c = a * b;
Putem combina operațiile și regulile matematice se aplică:
1 int a = 2;
2 int b = 4;
3 int c = 3 + a * b;
Valoarea variabilei c va fi 11. Dacă dorim să modificăm ordinea firească a
operațiilor, putem folosi paranteze:

1 int a = 2;
2 int b = 4;
3 int c = (3 + a) * b;
În acest caz valoarea variabilei c va fi 20. Putem avea și paranteze în paranteze,
dar nu chiar ca la matematică. Nu folosim paranteze drepte sau acolade. Toate
parantezele sunt rotunde:

1 int a = 2;
2 int b = 4;
3 int c = (3 + a * (a - 2)) * b;
De data aceasta c va avea valoarea 12. Prima dată se calculează valoarea a - 2;
rezultatul este 0. Urmează înmulțirea valorii variabilei a cu acest rezultat fiindcă
înmulțirile se efectuează înaintea adunărilor dacă nu sunt paranteze; noul rezultat
este tot 0. Urmează adunarea între 3 și acest rezultat (obținem 3), iar apoi
înmulțirea cu b care duce la rezultatul final: 12.

Împărțirea
Dacă împărțim numărul 3 la 2 spunem fie că rezultatul este 1.5, fie că obținem
câtul 1 și restul 1. În Java, dacă împărțim două numere întregi, rezultatul operației
este câtul, iar operatorul folosit este /. Dacă unul dintre numere este cu zecimale,
atunci rezultatul este și el cu zecimale, nu doar câtul. Să vedem un exemplu:
1 int a = 3;
2 int b = 2;
3 int c = a / b;
Valoarea variabilei c va fi 1. Dar, dacă avem:

1 double a = 3;
2 double b = 2;
3 double c = a / b;
valoarea variabilei c va fi 1.5. Rezultatul va fi cu zecimale, dacă cel puțin unul
dintre cele două numere este cu zecimale. De exemplu, și în următorul caz
rezultatul este tot 1.5:

1 double a = 3;
2 int b = 2;
3 double c = a / b;
La fel stau lucrurile în situația următoare:

1 int a = 3;
2 double b = 2;
3 double c = a / b;
Însă, dacă cele două numere împărțite sunt întregi, rezultatul este 1, chiar dacă
variabila căreia i-l atribuim reprezintă un număr cu zecimale:
1 int a = 3;
2 int b = 2;
3 double c = a / b;
Putem face experimente mai interesante. Nu trebuie să folosim neapărat variabile;
valorile simple sunt suficiente. Încercați să vă dați seama ce valori vor avea
variabilele declarate astfel:

1 double a = 3 / 2;
2 double b = 3 / 2.0;
3 double c = 3.0 / 2;
4 double d = 3.0 / 2.0;
În Java, dacă scriem 2, numărul este întreg, dar dacă scriem 2.0 el este considerat
cu zecimale (partea fracționară fiind 0). Pe baza acestei informații ne dăm seama
destul de ușor că valoarea variabilei a va fi 1, iar celelalte trei vor avea
valoarea 1.5.
Spuneam că dacă împărțim două numere întregi, rezultatul va fi câtul operației
matematice. Ni se oferă și posibilitatea de a afla restul. Pentru aceasta vom folosi
un alt operator, anume %.  În situația:

1 int a = 5;
2 int b = 3;
3 int c = a % b;
valoarea variabilei c va fi 2.
Deși e oarecum bizar, operatorul % poate fi folosit și pentru numere cu zecimale.
Rezultatul este tot un fel de rest; se calculează partea întreagă a împărțirii și
rezultatul este dat de "ce rămâne". Să vedem un exemplu:

1 double a = 8;
2 double b = 2.5;
3 double c = a % b;
Valoarea variabilei c va fi 0.5. Partea întreagă a împărțirii este 3; pentru acest
rezultat se "consumă" 7.5 din 8 și "rămâne" 0.5.
Am văzut că putem transforma un număr întreg în unul cu zecimale adăugând .0.
Avem și alternative: putem adăuga f, F, d sau D. Spuneam că numerele sunt
numere simple dacă nu apare nimic legat de ele. Dacă adăugăm una dintre aceste
litere schimbăm semnificația. Practic, transformăm un număr întreg într-unul cu
zecimale. În Java avem două tipuri pentru astfel de numere: float și double.
Dacă adăugăm f sau F, numărul este considerat a fi de tip float; dacă
adăugăm d sau D, el este considerat a fi de tip double. Deocamdată nu are
relevanță dacă avem float sau double...

Operații logice
Putem efectua operații și cu variabilele booleene. Chiar dacă au doar două valori
posibile, există operații care pot fi efectuate. În primul rând avem negația; este o
operație prin care adevărul devine fals și falsul devine adevăr. Operatorul este !; să
îl folosim în cele două posibile situații:

1 boolean a = true;
2 boolean b = false;
3 boolean c = !a;
4 boolean d = !b;
Valoarea variabilei c va fi false, iar cea a variabilei d va fi true.
Dar, avem și operații puțin mai complicate.

De exemplu, putem efectua o operație care să ne spună dacă două valori booleene


sunt ambele adevărate. Operația se numește ȘI; mai riguros, ea este
numită conjuncție. Să vedem un exemplu:

1 boolean a = true;
2 boolean b = true;
3 boolean c = false;
4 boolean d = a & b;
5 boolean e = a & c;
Probabil v-ați dat seama, operatorul este &. Valoarea variabilei d va fi true, iar
cea a variabilei e va fi false.
O altă operație pe care o avem la dispoziție ne spune dacă cel puțin una dintre două
valori booleene este adevărată. Operația se numește SAU; mai riguros, ea este
numită disjuncție. De data aceasta operatorul este |.  Să vedem acum câteva
variante:

1 boolean a = true;
2 boolean b = true;
3 boolean c = false;
4 boolean d = false;
5 boolean e = a | b;
6 boolean f = a | c;
7 boolean g = c | d;
Doar g va avea valoarea false, fiindcă atât c, cât și d, au
valoarea false. e și f vor avea valoarea true fiindcă cel puțin una dintre cele
două variabile asupra căreia este efectuată operația are valoarea true (ambele
pentru e, doar prima pentru f).
Acest SAU logic nu prea seamănă cu cel pe care îl folosim natural. De exemplu,
dacă spunem că vrem o rochie roșie sau albastră, vrem să spunem că rochia poate fi
fie roșie, fie albastră. Nu vrem să spunem că rochia poate fi și roșie și albastră; nu
vrem nici să spunem că dorim două rochii, una roșie și una albastră (deși poate nu
ar deranja pe nimeni). Un alt exemplu ar fi când spunem că dorim banane sau
portocale; vrem una dintre cele două variante, nu amândouă.
Există o operație logică al cărei rezultat ne spune dacă exact una dintre cele două
valori booleene este adevărată. Rezultatul este false dacă ambele valori
sunt true sau dacă ambele valori sunt false. Acest sau natural este numit SAU
EXCLUSIV sau disjuncție exclusivă. Operatorul este ^; să vedem exemplul:

1 boolean a = true;
2 boolean b = true;
3 boolean c = false;
4 boolean d = false;
5 boolean e = a ^ b;
6 boolean f = a ^ c;
7 boolean g = c ^ d;
Doar f va avea valoarea true, fiindcă a are valoarea true și c are
valoarea false. e și g vor avea valoarea false fiindcă ambele variabile asupra
căreia este efectuată operația au aceeași valoare (true pentru e, false pentru g).

Operații cu string-uri
Operatorul + poate fi utilizat și pentru string-uri. Aplicat asupra a două varioabile
de tip String, operatorul duce la unirea acestora. De exemplu, rezultatul
operației "alpha" + "beta" este "alphabeta".  Operația poartă denumirea
de concatenare. Ne putem reaminti de o instrucțiune din programul din primul
episod:

1 System.out.println("Salut " + nume + "!");


Aici avem o concatenare de trei string-uri.
Rezultatul concatenării unor string-uri are tipul String. Dar, putem aplica
operatorul + și în cazul în care doar una dintre cele două valori are tipul String,
iar rezultatul este cel pe care îl așteptăm. Iată câteva exemple:

1 String a = "ceva";
2 int b = 2;
3 double c = 3;
4 boolean d = false;
5 String e = a + b;
6 String f = c + a;
7 String g = a + d;
Valoarea variabilei e va fi ceva2, cea a variabilei f va fi 3.0ceva, iar cea a
variabilei g va fi cevafalse. 3.0ceva pare cam ciudat; nu e 3ceva fiindcă
numerele cu zecimale apar cu zecimale chiar dacă partea fracționară lipsește.

Atribuiri mai interesante


Ce-ați zice dacă o variabilă ar apărea de ambele părți ale semnului = ale unei
instrucțiuni de atribuire. Următoarea secvență este validă, dar nu prea interesantă
fiindcă nu se întâmplă nimic special:

1 int a = 1;
2 a = a;
Totuși, am putea avea o expresie în dreapta. De exemplu:

1 int a = 1;
2 a = a + 1;
Dacă a = a + 1 ar fi fost o ecuație, așa ceva nu ar avea sens. Dar, instrucțiunea
de mai sus se traduce astfel: preia valoarea variabilei a, adună 1 și pune rezultatul
în variabila a. Inițial a are valoarea 1, adunăm 1 și obținem 2 și a primește
valoarea 2. Faptul că acest lucru este posibil este foarte util. Vă mai amintiți
exemplul cu variabila goluriGazde care conține numărul golurilor înscrise de
echipa gazdă într-un meci de fotbal. În momentul în care echipa gazdă marchează
un gol, valoarea acestei variabile trebuie să devină mai mare cu 1. Am putea scrie:

1 goluriGazde = goluriGazde + 1;
De fapt, astfel de instrucțiuni sunt atât de des folosite, încât ni se oferă posibilitatea
să o scriem și prescurtat. Următoarea instrucțiune este echivalentă:

1 goluriGazde += 1;
Mai mult, atât de des este nevoie ca valoarea unei variabile să fie mărită cu exact 1,
încât avem la dispoziție o prescurtare suplimentară:

1 goluriGazde++;
Există și varianta ++goluriGazde, care are același efect. Pentru a explica
diferența sunt necesare cunoștințe mai avansate; deocamdată vom considera că cele
două variante sunt echivalente. Operația prin care valoarea unei variabile crește
cu 1 este numită incrementare.
Pentru majoritatea operatorilor avem variante prescurtate: există -
=, *=, /=, %=, &=, |= și multe altele.
Avem o prescurtare suplimentară și pentru decrementare (valoarea unei variabile
scade cu 1). Operatorul corespunzător este --; el poate apărea înainte sau după
variabilă.

Despre spații
În cadrul diverselor secvențe de cod prezentate până acum ați văzut că, în cadrul
instrucțiunilor, diverse elemente sunt separate prin spații. Aceste spații pot lipsi de
cele mai multe ori și, în marea majoritate a cazurilor, putem pune oricâte spații.

Spațiul este obligatoriul doar dacă absența sa ar crea confuzii. De exemplu, există o
mare diferență între int a = 2  și inta = 2 . Prima variantă declară o variabilă a și o
inițializează cu valoarea 2. Cea de-a doua atribuie variabilei inta valoarea 2.
Dacă o astfel de variabilă nu a fost declarată anterior, atunci instrucțiunea nu este
validă. Dar, de exemplu, putem elimina spațiile din jurul operatorului =;
varianta int a=2  reprezintă o declarație cu inițializare validă. Putem pune și mai
multe spații dacă dorim:

1 int   a            =2;
Nu arată foarte bine, dar este corect. De fapt, de cele mai multe ori modul în care
utilizăm spațiile are rol estetic; ne ajută să vedem mai ușor codul.
Pentru a separa elementele limbajului, putem folosi și taburi sau putem trece pe o
linie nouă. Nu prea putem ilustra aici taburile (ar arăta tot ca niște spații), dar putem
ilustra folosirea mai multor linii:

1 int
2      a
3   =2
4
5;
Din nou, parcă nu am vrea să arate așa codul nostru, dar este permis. După cum
vedeți, am folosit și multe linii și multe spații.

Simbolurile care nu se văd și sunt folosite pentru a separa diverse elemente poartă


denumirea de caractere albe. Deocamdată am văzut că astfel de caractere sunt
spațiile, taburile și marcajele de sfârșit de linie.
Trebuie precizat faptul că în interiorul string-urilor caracterele albe își păstrează
semnificația. De exemplu, string-urile "a   b" și "a b" sunt diferite.

Comentarii
Uneori scriem cod pe care dorim să nu îl mai folosim deocamdată, dar poate vom
avea nevoie în viitor. Putem marca acest cod astfel încât el să nu se execute.
Porțiunile marcate astfel poartă denumirea de comentarii.
În Java avem două tipuri de comentarii. Pe o linie, putem pune secvența // și tot
ce urmează după ea este comentariu.
Putem folosi și comentarii pe mai multe linii. Vom marca începutul comentariului
prin /* și sfârșitul său prin */.
Dacă // sau /* apar în interiorul unui string, atunci își pierd semnificația. De
exemplu String s = "a//a"; este o instrucțiune care inițializează string-
ul s cu valoarea a//a. La fel, nu avem un comentariu în instrucțiunea String s
= "a/*a";.
Dar, putem folosi comentariile nu numai pentru a elimina temporar cod, ci și pentru
a-l explica. Când altcineva citește codul nostru, îi va fi mult mai ușor să înțeleagă
dacă acesta conține explicații. Acel "altcineva" poate fi chiar persoana care a scris
codul, o lună mai târziu. În multe cazuri ne va fi foarte greu să ne dăm seama ce și
cum am vrut să facem.

Trebuie să fim puțin atenți în câteva situații. Să presupunem că avem următorul


cod:

1 int a = 1;
2 int b = 2;
3 int c = 3;
4 int d = 4;
5 int e = 5;
6 int f = 6;
Să presupunem că nu mai avem nevoie de variabilele c și d. Am putea comenta
liniile corespunzătoare:

1 int a = 1;
2 int b = 2;
3 /*int c = 3;
4 int d = 4;*/
5 int e = 5;
6 int f = 6;
Dacă dorim să arate mai frumos, am putea și așa:

1 int a = 1;
2 int b = 2;
3 /*
4 int c = 3;
5 int d = 4;
6 */
7 int e = 5;
8 int f = 6;
Acum să presupunem că am dori să scăpăm și de variabilele b și e. Soluția care
pare la îndemână ar fi:
1 int a = 1;
2 /*
3 int b = 2;
4 /*
5 int c = 3;
6 int d = 4;
7 */
8 int e = 5;
9 */
10 int f = 6;
Dar... nu am luat în considerare faptul că ce apare în interiorul comentariului este
ignorat până în momentul în care este întâlnită secvența care marchează sfârșitul
comentariului. Comentariul nostru începe pe linia 2 și secvența de sfârșit este
întâlnită pe linia 7. Secvența de pe linia 9 este acum invalidă.

Un alt exemplu interesant ar putea fi următorul:

1 /*
2 Operatorii admiși sunt +-*/%
3 */
Am putea crede că avem un simplu comentariu care ne spune care sunt operatorii
permiși într-o anumită situație. Dar, înșirurirea operatorilor conține secvența */ care
indică sfârșitul comentariului. Ce rămâne nu mai este corect.

Va urma
În cadrul următorului episod vom vedea cum programele pot lua anumite decizii în
funcție de împrejurări.
Java - Lecția 04
DE MIHAI SCORȚARU · 25 MAI 2015
În cadrul acestui episod vom vedea cum putem face în așa fel încât programele să
ia anumite decizii în funcție de circumstanțe.

Până acum am scris doar programe sau scurte secvențe de cod în care instrucțiunile
se executau în ordine, începând cu prima și terminând cu ultima. Nimic nu putea
afecta acest proces. Dar, programele trebuie să poată face mai mult decât atât...

Să ne imaginăm că ajungem la o răscruce de drumuri; cel din dreapta


duce spre Împărăția Roșie, iar celălalt spre Împărăția Verde. În funcție de unde
vrem să ajungem, vom alege drumul din dreapta sau cel din stânga.
Pentru a o lua la dreapta, trebuie ca o anumită condiție să fie îndeplinită; trebuie să
vrem să mergem în Împărăția Roșie. Pentru a o lua la stânga, trebuie ca acea
condiția să nu fie îndeplinită; trebuie să nu vrem să mergem în Împărăția Roșie,
ceea ce înseamnă că vrem să mergem în Împărăția Verde.
Condiția poate lua diverse forme. În exemplul anterior condiția a fost voința
noastră; dar, ar putea să fie ceva mai interesant; de exemplu, am putea spune că
dacă în caleașca pe care o însoțim se află o prințesă, atunci vom merge în Împărăția
Roșie.

Instrucțiunea if
Pentru a explica ce vrem să facem, am folosit cuvântul dacă; am spus că dacă o
anumită condiție este îndeplinită vom efectua o anumită acțiune. Și în Java vom
folosi ceva similar; va fi în engleză, deci cuvântul va fi if. El va fi urmat de condiția
care trebuie verificată, cuprinsă între paranteze rotunde și apoi de instrucțiunea care
trebuie executată în cazul în care condiția este îndeplinită. Condiția este o expresie
booleană; poate fi o simplă variabilă sau o expresie mai complexă. O astfel de
instrucțiune este numită condițională.
Să presupunem că avem o variabilă existaPrintesa care are o anumită valoare; nu
știm exact cum a fost atribuită acea valoare și nici care este valoarea sa curentă.
Dar, dacă în acest moment această variabilă are valoarea true, dorim să scriem
mesajul "Împărăția Roșie". Secvența de cod ar arăta astfel:
1 if (existaPrintesa) System.out.println("Împărăția Roșie");
Secvența este corectă, dar nu arată prea bine. De obicei instrucțiunea care ar trebui
executată atunci când este îndeplinită condiția este scrisă pe o linie nouă.

1 if (existaPrintesa)
2     System.out.println("Împărăția Roșie");

Blocuri de instrucțiuni
Deocamdată, dacă este îndeplinită condiția executăm o singură instrucțiune. Dar, s-
ar putea să vrem să executăm mai multe. De exemplu, am putea să vrem să ducem
prințesa în Împărăția Roșie și să o lăsăm acolo; când ajunge acasă, prințesa va
coborî din caleașcă, deci în caleașcă nu se va mai afla nicio prințesă. Așadar,
variabila existaPrintesa ar trebui să primească valoarea false. Am putea verifica din
nou dacă este îndeplinită condiția; codul ar putea fi următorul:

1 if (existaPrintesa)
2     System.out.println("Împărăția Roșie");
3 if (existaPrintesa)
4     existaPrintesa = false;
Nu arată deloc bine... Ce am vrea este să scriem condiția o singură dată și să
executăm mai multe instrucțiuni. Pentru aceasta va trebui să creăm un așa numit
bloc de instrucțiuni. Un astfel de bloc este format dintr-o succesiune de instrucțiuni,
cuprinse între acolade. Putem rescrie secvența astfel:
1 if (existaPrintesa) {
2     System.out.println("Împărăția Roșie");
3     existaPrintesa = false;
4}
O practică des întâlnită este să se creeze blocuri de instrucțiuni formate dintr-o
singură instrucțiune; codul este mai clar și sunt evitate anumite greșeli puțin mai
greu de detectat.

Să presupunem că avem prima variantă: cea în care doar scriem string-


ul "Împărăția Roșie". Dorim acum ca, pe lângă acest mesaj, pe o altă linie să scriem
și string-ul "Prințesa a ajuns acasă". Dacă ne grăbim, codul nostru ar putea arăta
așa:

1 if (existaPrintesa)
2     System.out.println("Împărăția Roșie");
3     System.out.println("Prințesa a ajuns acasă");
Deși am aliniat instrucțiunea cu cea anterioară, spațiile se ignoră, deci nu are nicio
importanță. Avem o instrucțiunei if care spună că, în cazul în care condiția este
îndeplinită, se execută instrucțiunea care urmează. Cealaltă instrucțiune se execută
oricum; condiția nu mai este verificată. Deci, mesajul "Prințesa a ajuns acasă" ar fi
afișat chiar dacă nu am fi avut nicio prințesă în caleașcă.
Dar, dacă am fi folosit acolade chiar și în prima variantă:

1 if (existaPrintesa) {
2     System.out.println("Împărăția Roșie");
3}
atunci, după adăugarea celei de-a doua instrucțiui, codul ar deveni:

1 if (existaPrintesa) {
2     System.out.println("Împărăția Roșie");
3     System.out.println("Prințesa a ajuns acasă");
4}
și ar fi funcționat așa cum ne-am dori.

Altfel de condiții
Spuneam că acea condiție este o expresie booleană. Până acum am folosit o simplă
variabilă booleană; este ușor să ne gândim că putem folosi operatorii booleeni pe
care i-am prezentat în episodul trecut. Poate dacă în caleașcă se află și un prinț,
dorim de fapt să mergem la nunta din Împărăția Verde. Codul ar putea arăta așa:

1 if (existaPrintesa & existaPrint) {


2     System.out.println("Împărăția Verde");
3}
Dar, de obicei condițiile pe care dorim să le verificăm sunt cu totul altele. Dacă
lucrăm cu numere, am putea dori să verificăm dacă un număr are o anumită
valoare, să vedem dacă un număr este mai mare decât altul etc.

Să considerăm un prim exemplu: avem o variabilă nr care conține un număr întreg;


în cazul în care valoarea acelei variabile este 2457, dorim să scriem
mesajul "Număr magic". Codul este:

1 if (nr == 2457) {
2     System.out.println("Număr magic");
3}
Observăm că nu am scris un singur simbol =, ci două; == este operatorul de
egalitate. Folosim un singur = pentru atribuire. Secvența următoare nu este validă:

1 if (nr = 2457) {
2     System.out.println("Număr magic");
3}
Operatorul de egalitate este aplicat asupra a doi operatori cu tipuri compatibile;
pentru tipurile primitive nu avem nicio surpriză; rezultatul este o valoare booleană
care arată dacă cele două valori sunt egale.

Avem și un operator de inegalitate; rezultatul arată dacă cele două valori nu sunt
egale.

1 if (nr != 2457) {
2     System.out.println("Numărul nu este magic!");
3}
După cum vedeți, operatorul este !=. Intuitiv, am putea spune că am negat
egalitatea; am folosit semnul exclamării (cel care indică negația) urmat de semnul
egal.
Dar, numerele pot fi și comparate; nu ar trebui să ne surprindă deloc existența unor
operatori ca < sau >. Să verificăm dacă un număr este strict pozitiv:

1 if (nr > 0) {
2     System.out.println("Număr strict pozitiv!");
3}
La fel de simplu este să verificăm dacă numărul este strict negativ:

1 if (nr < 0) {
2     System.out.println("Număr strict negativ!");
3}
Când comparăm numerele folosim câteodată și conceptul de mai mare sau egal.
Avem și un operator pentru așa ceva; nu este chiar ≥ cum poate ne-ar plăcea, ci >=.
Să vedem cum verificăm dacă un număr este pozitiv (nu strict pozitiv):
1 if (nr >= 0) {
2     System.out.println("Număr pozitiv!");
3}
Similar, avem operatorul <= pentru mai mic sau egal.

Condiții compuse
Rezultatul utilizării oricărui astfel de operator este o valoare booleană; este natural
să ne așteptăm să putem folosi operatorii booleeni asupra rezultatelor.

Am putea dori să verificăm dacă un anumit număr întreg este format dintr-o singură
cifră. Am avea o condiția dublă: numărul trebuie să fie mai mare sau egal cu zero și
mai mic decât zece. Am putea scrie următorul cod:

1 if (nr >= 0 & nr < 10) {


2     System.out.println("O cifră");
3}
Mai avem și alte variante; una ar putea fi:

1 if (nr > -1 & nr <= 9) {


2     System.out.println("O cifră");
3}
Codul funcționează corect fiindcă operațiile de comparare sunt executate înaintea
conjucției logice; există o ordine specifică limbajului și de data aceasta ordinea de
convine; dar, ar fi cam mult să ținem minte ordinea luată în considerare de limbaj;
de obicei vrem să ne asigurăm că operațiile sunt efectuate în ordinea pe care o
dorim; pentru aceasta folosim paranteze, chiar dacă nu sunt neapărat necesare;
codul poate fi înțeles mult mai ușor. Așadar, varianta recomandată ar fi:
1 if ((nr >= 0) & (nr < 10)) {
2     System.out.println("O cifră");
3}
Avem paranteze în paranteze, dar totul este în regulă; totuși, să nu vă gândiți că am
putea folosi paranteze drepte sau acolade; am întâlnit deja acolade și am văzut că au
cu totul alt rol (delimitează grupuri de instrucțiuni); vom întâlni și paranteze drepte,
care au și ele un rol diferit.

Deși nu prea are sens să scriem un astfel de cod, pentru a ilustra că nu tot timpul
ordinea este cea pe care am dori-o să verificăm dacă un număr este diferit
del 2457 verificând egalitatea și negând rezultatul. Codul ar arăta așa:

1 if (! nr == 2457) {
2     System.out.println("Numărul nu este magic!");
3}
Vom observa că este generată o eroare care ne spune că operatorul logic de negație
nu poate fi aplicat asupra unui număr întreg. Totul se rezolvă dacă scriem:

1 if (!(nr == 2457)) {
2     System.out.println("Numărul nu este magic!");
3}
În Java mai avem la dispoziție doi operatori pentru condițiile compuse care ar
putea fi utili. Este vorba de && și ||. Ei seamănă cu  & și |, dar există o șmecherie.
Dacă avem && și prima dintre cele două condiții este falsă, atunci a doua nu mai
este verificată fiindcă rezultatul ar fi false oricum. Similar, dacă avem || și prima
dintre cele două condiții este adevărată, atunci a doua nu mai este verificată fiindcă
rezultatul ar fi true oricum. Deocamdată nu pare foarte important; dar, dacă ne
gândim că aceste condiții pot deveni din ce în ce mai complicate, ne putem imagina
că am putea ajunge să economisim timp dacă nu facem verificări inutile. Să
revenim la codul care verifică dacă un număr are o singură cifră, dar să dublăm
ampersandul:

1 if ((nr >= 0) && (nr < 10)) {


2     System.out.println("O cifră");
3}
Dacă numărul ar fi negativ, prima condiție este falsă și nu mai are rost să verificăm
dacă el este mai mic decât zece. Chiar dacă ar fi (și în cazul nostru știm că va fi
fiindcă este negativ), nu are nicio relevanță; condiția compusă va fi falsă.

Alternativa
Să revenim la exemplul inițial; spuneam că dacă avem o prințesă în caleașcă vrem
să mergem în Împărăția Roșie. Probabil că dacă nu însoțim nicio prințesă am vrea
totuși să mergem în Împărăția Verde (poate găsim o prințesă acolo?). Pentru a
verifica dacă trebuie să mergem în Împărăția Verde, am putea nega condiția; codul
ar arăta astfel:

1 if (existaPrintesa) {
2     System.out.println("Împărăția Roșie");
3}
4 if (!existaPrintesa) {
5     System.out.println("Împărăția Verde");
6}
Deocamdată nu avem nicio problemă, dar pare complicat și ne putem imagina că în
situații complexe ar deveni din ce în ce mai ciudat. Codul pe care l-am scris ar
putea fi descris astfel: dacă în caleașcă este o prințesă mergem în Împărăția Roșie;
dacă în caleașcă nu este o prințesă mergem în Împărăția Verde. Pare puțin ciudat
și cam lung; ne-am aștepta ca raționamentul să fie ceva de genul: dacă în caleașcă
este o prințesă mergem în Împărăția Roșie; altfel mergem în Împărăția Verde. Din
fericire, Java și majoritatea limbajelor de programare ne permit să "spunem" altfel.
Cuvântul va fi în engleză: else.
În Java vom avea cuvântul if, urmat de condiția care trebuie verificată, cuprinsă
între paranteze rotunde, de instrucțiunea care trebuie executată în cazul în care
condiția este îndeplinită, apoi de cuvântul else și de instrucțiunea care trebuie
executată în cazul în care condiția este îndeplinită.
Codul nostru devine:

1 if (existaPrintesa) {
2     System.out.println("Împărăția Roșie");
3 } else {
4     System.out.println("Împărăția Verde");
5}

If în if
Am spus că în cazul în care este îndeplinită o condiție se execută o instrucțiune.
Am mai arătat că dacă nu este îndeplinită condiția, putem specifica o altă
instrucțiune care să fie executată. Nu am pus nicio restricție legată de tipul
instrucțiunilor respective. De fapt, nu există nicio restricție. Am văzut că putem
pune o instrucțiune simplă sau un bloc de instrucțiuni. Dar, putem pune chiar și o
altă instrucțiune condițională. De fapt, și printre instrucțiunile care formează un
bloc, oricare poate fi un if.
Așadar, putem verifica o condiție și apoi, printre operațiile pe care le efectuăm,
putem verifica o altă condiție și efectua alte operații în funcție de ea.

Să extindem puțin exemplul inițial; la răscrucea de drumuri putem alege trei


variante: spre Împărăția Roșie, spre Împărăția Verde sau spre Împărăția Albastră.
În caleașcă putem avea sau nu o prințesă și putem sau nu avea un prinț. Dacă
prințesa nu este în caleașcă, atunci mergem în Împărăția Albastră să aducem
prințesa; dacă e în caleașcă și nu e însoțită, mergem în Împărăția Verde să luăm
prințul; dacă e însoțită de prinț, mergem la nuntă în Împărăția Roșie.
Așadar, vom avea o condiția care verifică dacă prințesa există. Dacă da, atunci
trebuie să verificăm dacă există și prințul. Dacă prințul există, scriem
mesajul "Împărăția Roșie". Dacă prințul nu există, scriem mesajul "Împărăția
Verde". Dacă prințesa nu există, scriem mesajul "Împărăția Albastră" indiferent
dacă prințul există sau nu.
Codul ar putea arăta așa:

1 if (existaPrintesa) {
2     if (existaPrint) {
3         System.out.println("Împărăția Roșie");
4     } else {
5         System.out.println("Împărăția Verde");
6     }
7 } else {
8     System.out.println("Împărăția Albastră");
9}
De data aceasta putem și fără acolade, deși nu este recomandat:

1 if (existaPrintesa)
2     if (existaPrint)
3         System.out.println("Împărăția Roșie");
4     else
5         System.out.println("Împărăția Verde");
6 else
7     System.out.println("Împărăția Albastră");
Nu trebuie neapărat să ne oprim la un singur if în if. Cel din interior poate conține
la rândul său o instrucțiune condițională; la fel acest al treilea if și așa mai departe.
Când avem două sau mai multe astfel de instrucțiuni if, spunem că ele
sunt imbricate.
Să vedem de ce este periculos să nu folosim acolade. Poate nu vrem să facem
absolut nimic în cazul în care avem prințesă dar nu avem prinț. Am putea crede că
este suficient să eliminăm liniile 4 și 5. Codul ar deveni:

1 if (existaPrintesa)
2     if (existaPrint)
3         System.out.println("Împărăția Roșie");
4 else
5     System.out.println("Împărăția Albastră");
Vă mai aduceți aminte cum calculatoarele fac ceea ce le spunem să facă, nu ceea ce
vrem noi să facă? Degeaba avem acel else la începutul liniei 4; calculatorul nu are
cum să știe că noi vrem ca acesta să fie alternativa pentru primul if; caracterele albe
sunt ignorate; e ca și cum am scrie:

1 if (existaPrintesa)
2     if (existaPrint)
3         System.out.println("Împărăția Roșie");
4     else
5         System.out.println("Împărăția Albastră");
Cum alege calculatorul? De data aceasta nu cum vrem noi! Un else reprezintă
alternativa pentru cel mai apropiat if.
Dacă am fi transformat codul care avea acolade, noua versiune ar fi fost:

1 if (existaPrintesa) {
2     if (existaPrint) {
3         System.out.println("Împărăția Roșie");
4     }
5 } else {
6     System.out.println("Împărăția Albastră");
7}
De data aceasta obținem ce ne-am dorit; datorită faptului că al doilea if  face parte
dintr-un bloc și acel bloc s-a încheiat, alternativa nu se poate aplica decât
primului if.

Va urma
În următorul episod vom vedea ce opțiuni avem la dispoziție în cazul în care o
anumită variabilă (sau expresie) poate avea diferite valori și trebuie să executăm
diverse instrucțiuni în funcție de fiecare valoare în parte.
Java - Lecția 05
DE MIHAI SCORȚARU · 1 IUNIE 2015
Am văzut în cadrul episodului anterior cum pot lua programele decizii în funcție de
circumstanțe, cum se execută o instrucțiune sau alta în funcție de anumite condiții.
În cadrul acestui episod vom continua prezentarea modului în care sunt luate
decizii.

Mai multe variante


Până acum doream să se execute anumite instrucțiuni dacă o anumită condiție era
adevărată și altele dacă era falsă. Dar, ce am face dacă nu avem doar două variante,
ci mai multe.

Să ne imaginăm o situție în care dorim să scriem cifrele folosind litere. Avem o


variabilă c care ar trebui să conțină o cifră. Dacă valoarea este 1, ar trebui să scriem
string-ul "unu"; dacă valoarea este 2, ar trebui să scriem "doi" și așa mai departe.
Variabila conține numere, deci probabil nu va avea neapărat valori cuprinse între
zero și nouă; în cazul în care valoarea nu este o cifră, am vrea să scriem textul "nu
este o cifră".
Cea mai simplă variantă este să comparăm, pe rând, valoarea variabilei c cu fiecare
cifră și să scriem mesajul corespunzător în cazul în care identificăm cifra; începem
comparând cu zero; dacă am găsit valoarea scriem textul "zero"; dacă nu am găsit-o
încercăm să comparăm cu unu și așa mai departe; dacă am ajuns la nouă și tot nu
am găsit cifra, putem concluziona că nu avem o cifră. Codul ar arăta astfel:

1 if (c == 0) {
2     System.out.println("zero");
3 } else {
4     if (c == 1) {
5         System.out.println("unu");
6     } else {
7         if (c == 2) {
8             System.out.println("doi");
9         } else {
10             if (c == 3) {
11                 System.out.println("trei");
12             } else {
13                 if (c == 4) {
14                     System.out.println("patru");
15                 } else {
16                     if (c == 5) {
17                         System.out.println("cinci");
18                     } else {
19                         if (c == 6) {
20                             System.out.println("șase");
21                         } else {
22                             if (c == 7) {
23                                 System.out.println("șapte");
24                             } else {
25                                 if (c == 8) {
26                                     System.out.println("opt");
27                                 } else {
28                                     if (c == 9) {
29                                         System.out.println("nouă");
30                                     } else {
31                                         System.out.println("nu este o cifră");
32                                     }
33                                 }
34                             }
35                         }
36                     }
37                 }
38             }
39         }
40     }
41 }
Am respectat recomandarea de a folosi blocuri de instrucțiuni chiar dacă avem o
singură instrucțiune și nu arată prea bine...

Trebuie să ne obișnuim ca, în funcție de situație, să avem recomandări, excepții de


la recomandări, excepții de la excepții etc. De data aceasta recomandarea nu a dus
la ceva bun, deci vom introduce o excepție (tot sub formă de recomandare). Avem
aici o succesiune if, else, if, else, if, else, etc. În situația în care pe
ramura else avem doar un if, noua recomandare este să nu folosim un bloc de
instrucțiuni, ci o instrucțiune condițională simplă. Se poate vedea că arată mult mai
bine:

1 if (c == 0) {
2     System.out.println("zero");
3 } else if (c == 1) {
4     System.out.println("unu");
5 } else if (c == 2) {
6     System.out.println("doi");
7 } else if (c == 3) {
8     System.out.println("trei");
9 } else if (c == 4) {
10     System.out.println("patru");
11 } else if (c == 5) {
12     System.out.println("cinci");
13 } else if (c == 6) {
14     System.out.println("șase");
15 } else if (c == 7) {
16     System.out.println("șapte");
17 } else if (c == 8) {
18     System.out.println("opt");
19 } else if (c == 9) {
20     System.out.println("nouă");
21 } else {
22     System.out.println("nu este o cifră");
23 }

Switch
Chiar și așa, pare totuși cam complicat; ar trebui să putem mai simplu. Ni se pune
la dispoziție instrucțiunea switch; aceasta seamănă cu instrucțiunea if, dar are mai
multe "ramuri"; în locul condiției avem o expresie al cărei rezultat trebuie să fie un
număr întreg sau un string. Putem apoi specifica instrucțiunile care trebuie
executate pentru fiecare valoare în parte; de asemenea, putem specifica instrucțiuni
care să se execute în cazul în care nu se potrivește nicio valoare.
Fiecare alternativă este specificată folosind cuvântul case, urmat de o valoare, apoi
de semnul : și, în sfârșit, instrucțiunile care trebuie executate. Pot fi mai multe
instrucțiuni; acestea nu trebuie grupate într-un bloc.
Putem specifica și o ultimă alternativă (nicio valoare nu se potrivește)
folosind cuvântul default, urmat de semnul : și de instrucțiunile care trebuie
executate în acest caz.
Alternativele sunt cuprinse între acolade.

Limbajul Java (la fel ca multe altele) are o abordare puțin ciudată. Dacă expresia se
potrivește cu una din valorile specificate, atunci se execută toate instrucțiunile care
urmează, inclusiv de la alternativele prezentate ulterior.
Să vedem exact ce înseamnă acest lucru... Pe baza celor prezentate, ne-am aștepta
ca problema noastră inițială să poată fi rezolvată folosind următorul cod:
1 switch (c) {
2 case 0:
3     System.out.println("zero");
4 case 1:
5     System.out.println("unu");
6 case 2:
7     System.out.println("doi");
8 case 3:
9     System.out.println("trei");
10 case 4:
11     System.out.println("patru");
12 case 5:
13     System.out.println("cinci");
14 case 6:
15     System.out.println("șase");
16 case 7:
17     System.out.println("șapte");
18 case 8:
19     System.out.println("opt");
20 case 9:
21     System.out.println("nouă");
22 default:
23     System.out.println("nu este o cifră");
24 }
Dacă am avea valoarea 4, ne-am aștepta să fie afișat textul "patru". Dar, în realitate,
afișăm mult mai mult:

1 patru
2 cinci
3 șase
4 șapte
5 opt
6 nouă
7 nu este o cifră
Nu este ceea ce ne dorim, dar așa funcționează în Java. Totuși, avem o
soluție: Java ne pune la dispoziție instrucțiunea break  care duce la întreruperea
executării instrucțiunilor. O putem folosi pentru a spune că nu dorim să se execute
ceea ce urmează. Obținem ceea ce ne-am dori dacă rescriem codul astfel:

1 switch (c) {
2 case 0:
3     System.out.println("zero");
4     break;
5 case 1:
6     System.out.println("unu");
7     break;
8 case 2:
9     System.out.println("doi");
10     break;
11 case 3:
12     System.out.println("trei");
13     break;
14 case 4:
15     System.out.println("patru");
16     break;
17 case 5:
18     System.out.println("cinci");
19     break;
20 case 6:
21     System.out.println("șase");
22     break;
23 case 7:
24     System.out.println("șapte");
25     break;
26 case 8:
27     System.out.println("opt");
28     break;
29 case 9:
30     System.out.println("nouă");
31     break;
32 default:
33     System.out.println("nu este o cifră");
34 }
Nu are sens să punem break și pentru alternativa default fiindcă e ultima. Această
variantă face ceea ce ne dorim.

Operatorul condițional
De multe ori dorim să verificăm o anumită condiție booleană și, în funcție de
rezultatul verificării să atribuim unei variabilă o valoare sau alta. De exemplu, am
putea avea o variabilă nr care conține numere întregi și am dori să atribuim unei
variabile s care conține string-uri valoarea "negativ" dacă numărul respectiv este
mai mic decât zero și valoarea "nenegativ" în caz contrar (numărul este mai mare
sau egal cu zero).
Putem face asta simplu:

1 if (nr < 0) {
2     s = "negativ";
3 } else {
4     s = "nenegativ";
5}
Totuși, situația este atât de frecventă încât limbajele oferă o prescurtare și
anume operatorul condițional. Acesta este interesant: are trei operanzi; nu am mai
văzut așa ceva până acuma. Primul este o condiție booleană, iar ceilalți doi sunt
expresii. Rezultatul aplicării operatorului este detrminat astfel: în cazul în care
econdiția este îndeplinită, rezultatul este obținut prin evaluarea primeia dintre cele
două expresii; altfel, rezultatul este obținut prin evaluarea celeilalte expresii;
tipurile rezultatelor celor două expresii trebuie să fie compatibile.
Următoarea instrucțiune este echivalentă cu secvența anterioară:

1 s = nr < 0 ? "negativ" : "nenegativ";


Așadar, avem condiția, urmată de semnul ?, de prima expresie, semnul : și apoi de a
doua expresie.
Cum acest operator are ca rezultat o valoare, putem folosi astfel de expresii și
pentru inițializări de variabile. Următoarea inițializare este validă:

1 String s = nr < 0 ? "negativ" : "nenegativ";

Va urma
În următorul episod vom introduce conceptul de funcție. Vom vedea cum putem
grupa instrucțiunile și cum putea evita să scriem același lucru de mai multe ori.
Java - Lecția 06
DE MIHAI SCORȚARU · 8 IUNIE 2015
Pe măsură ce scriem din ce în ce mai mult cod, acesta devine mai greu de urmărit.
Vă amintiți de lunga secvență if, else, if din episodul anterior? Atunci am avut o
soluție cu switch, dar în alte situații instrucțiunile nu au astfel de caracteristici
comune. Totuși, am putea dori să le grupăm cumva. Am văzut că avem grupuri de
instrucțiuni, dar nici acestea nu sunt utile decât în anumite situații.
Ar fi frumos dacă am putea împărți codul în bucățele mici, ușor de înțeles, pe care
să le folosim cum vrem. Să ne imaginăm că vrem să tipărim versurile
din Gaudeamus. Deocamdată, programul nostru ar arăta cam așa:

1 /* package whatever; // don't place package name! */


2
3 import java.util.*;
4 import java.lang.*;
5 import java.io.*;
6
7 /* Name of the class has to be "Main" only if the class is public. */
8 class Ideone
9 {
10     public static void main (String[] args) throws java.lang.Exception
11     {
12         System.out.println("Gaudeamus igitur");
13         System.out.println("Iuvenes dum sumus.");
14         System.out.println("Post iucundam iuventutem");
15         System.out.println("Post molestam senectutem");
16         System.out.println("Nos habebit humus.");
17         System.out.println("");
18         System.out.println("Ubi sunt qui ante nos");
19         System.out.println("In mundo fuere?");
20         System.out.println("Vadite ad superos");
21         System.out.println("Transite in inferos");
22         System.out.println("Hos si vis videre.");
23         System.out.println("");
24         System.out.println("Vita nostra brevis est");
25         System.out.println("Brevi finietur.");
26         System.out.println("Venit mors velociter");
27         System.out.println("Rapit nos atrociter");
28         System.out.println("Nemini parcetur.");
29         System.out.println("");
30         System.out.println("Vivat academia!");
31         System.out.println("Vivant professores!");
32         System.out.println("Vivat membrum quodlibet;");
33         System.out.println("Vivant membra quaelibet;");
34         System.out.println("Semper sint in flore.");
35         System.out.println("");
36         System.out.println("Vivant omnes virgines");
37         System.out.println("Faciles, formosae.");
38         System.out.println("Vivant et mulieres");
39         System.out.println("Tenerae, amabiles,");
40         System.out.println("Bonae, laboriosae.");
41         System.out.println("");
42         System.out.println("Vivat et res publica");
43         System.out.println("et qui illam regit.");
44         System.out.println("Vivat nostra civitas,");
45         System.out.println("Maecenatum caritas");
46         System.out.println("Quae nos hic protegit.");
47         System.out.println("");
48         System.out.println("Pereat tristitia,");
49         System.out.println("Pereant osores.");
50         System.out.println("Pereat diabolus,");
51         System.out.println("Quivis antiburschius");
52         System.out.println("Atque irrisores.");
53     }
54 }
Cam lung și monoton, nu?

Împărțirea în funcții
Am spus că am vrea să împărțim acest cod în bucățele mai mici. O putem face
oricum, dar ar fi bine ca acele bucățele să aibă totuși un sens. De data aceasta este
natural să alegem o împărțire pe strofe. Fiecare strofă va fi scrisă de o bucată de
cod; o astfel de bucată de cod poartă denumirea de funcție. Prezentăm noua
variantă a codului și apoi vom discuta mai pe larg despre funcții (ce sunt și cum
sunt create).

1 /* package whatever; // don't place package name! */


2
3 import java.util.*;
4 import java.lang.*;
5 import java.io.*;
6
7 /* Name of the class has to be "Main" only if the class is public. */
8 class Ideone
9 {
10     private static void strofa1() {
11         System.out.println("Gaudeamus igitur");
12         System.out.println("Iuvenes dum sumus.");
13         System.out.println("Post iucundam iuventutem");
14         System.out.println("Post molestam senectutem");
15         System.out.println("Nos habebit humus.");
16         System.out.println("");
17     }
18
19     private static void strofa2() {
20         System.out.println("Ubi sunt qui ante nos");
21         System.out.println("In mundo fuere?");
22         System.out.println("Vadite ad superos");
23         System.out.println("Transite in inferos");
24         System.out.println("Hos si vis videre.");
25         System.out.println("");
26     }
27
28     private static void strofa3() {
29         System.out.println("Vita nostra brevis est");
30         System.out.println("Brevi finietur.");
31         System.out.println("Venit mors velociter");
32         System.out.println("Rapit nos atrociter");
33         System.out.println("Nemini parcetur.");
34         System.out.println("");
35     }
36
37     private static void strofa4() {
38         System.out.println("Vivat academia!");
39         System.out.println("Vivant professores!");
40         System.out.println("Vivat membrum quodlibet;");
41         System.out.println("Vivant membra quaelibet;");
42         System.out.println("Semper sint in flore.");
43         System.out.println("");
44     }
45
46     private static void strofa5() {
47         System.out.println("Vivant omnes virgines");
48         System.out.println("Faciles, formosae.");
49         System.out.println("Vivant et mulieres");
50         System.out.println("Tenerae, amabiles,");
51         System.out.println("Bonae, laboriosae.");
52         System.out.println("");
53     }
54
55     private static void strofa6() {
56         System.out.println("Vivat et res publica");
57         System.out.println("et qui illam regit.");
58         System.out.println("Vivat nostra civitas,");
59         System.out.println("Maecenatum caritas");
60         System.out.println("Quae nos hic protegit.");
61         System.out.println("");
62     }
63
64     private static void strofa7() {
65         System.out.println("Pereat tristitia,");
66         System.out.println("Pereant osores.");
67         System.out.println("Pereat diabolus,");
68         System.out.println("Quivis antiburschius");
69         System.out.println("Atque irrisores.");
70     }
71
72     public static void main (String[] args) throws java.lang.Exception
73     {
74         strofa1();
75         strofa2();
76         strofa3();
77         strofa4();
78         strofa5();
79         strofa6();
80         strofa7();
81     }
82 }
Vedem acum șapte noi porțiuni de cod, care încep cu ciudatul private static void.
Să ignorăm deocamdată aceste cuvinte...
Urmează o denumire; acesta este numele funcției. Avem apoi o paranteză deschisă,
urmată imediat de una închisă. Cam ciudat, dar să ignorăm și acest aspect
deocamdată (vom vedea în episodul următor mai multe despre aceste paranteze).
După aceea avem un simplu bloc de instrucțiuni; acesta este numit corpul funcției.
Până acum, în Java, codul pe care l-am scris a fost tot timpul între acoladele care
urmau după linia care începea cu public static void main. De data aceasta vedem că
funcțiile sunt undeva în afară. Dar, înauntru vedem șapte linii care conțin numele
celor șapte funcții, urmate de câte o paranteză deschisă și câte una închisă. Acestea
sunt instrucțiuni prin care spunem că dorim să se execute codul corespunzător unei
funcții. Ele poartă denumirea de apeluri de funcții.
Instrucțiunile din interiorul unei funcții nu se execută decât dacă funcția este
apelată. Dacă am șterge liniile 74 - 80 versurile nu ar mai fi afișate. De fapt, acum
putem alege ce strofe dorim să afișăm. Prin eliminarea unei linii, decidem că o
anumită strofă nu trebuie afișată. Vă mai amintiți de comentarii? Putem să nu
ștergem linia, ci doar să o comentăm.

Funcții apelate din funcții


Corpul funcției poate conține orice instrucțiuni, inclusiv un apel al unei alte funcții.
Să presupunem că primele versuri din prima strofă sunt speciale; la fel și ultimul
vers (vom vedea mai târziu de ce). Poate am dori să împărțim codul corespunzător
funcției strofa1 în mai multe bucățele: primele două versuri, următoarele două și
ultimul. Secțiunea corespunzătoare a codului ar putea arăta astfel:
1 private static void strofa1inceput() {
2     System.out.println("Gaudeamus igitur");
3     System.out.println("Iuvenes dum sumus.");
4 }
5
6 private static void strofa1mijloc() {
7     System.out.println("Post iucundam iuventutem");
8     System.out.println("Post molestam senectutem");
9 }
10
11 private static void strofa1sfarsit() {
12     System.out.println("Nos habebit humus.");
13 }
14
15 private static void strofa1() {
16     strofa1inceput();
17     strofa1mijloc();
18     strofa1sfarsit();
19     System.out.println("");
20 }
Avem acum o funcție care apelează alte trei funcții. Putem face același lucru și
pentru funcțiile corespunzătoare celorlalte strofe.

Apeluri multiple
Am spus că o funcție este executată doar dacă este apelată. Dar, ce ne împiedică să
o apelăm de mai multe ori? Nimic! Lăsăm nemodificate
funcțiile strofa1inceput, strofa1mijloc și strofa1sfarsit, dar modificăm
funcția strofa1 astfel:

1 private static void strofa1() {


2     strofa1inceput();
3     strofa1inceput();
4     strofa1mijloc();
5     strofa1sfarsit();
6     strofa1sfarsit();
7     System.out.println("");
8}
Acum funcția strofa1inceput este apelată de două ori, deci va fi executată de două
ori, deci primele două versuri vor fi afișate de două ori. Similar,
funcția strofa1sfarsit este apelată de două ori, deci va fi și ea executată de două ori
și ultimul vers va fi și el afișat de două ori.
De ce am face așa ceva? Când este cântat Gaudeamus, primele două versuri din
fiecare strofă sunt repetate; la fel și ultimul vers. Deci, dacă am ales o împărțire
potrivită a funcțiilor, am putut trece ușor de la poezie la cântec.
Ne putem gândi și la alte situații în care apelurile multiple ar putea fi utile. De
exemplu, am putea avea un cântec cu refren. Funcția care afișează refrenul ar
putea fi apelată de mai multe ori.

Va urma
În cadrul episodului următor, vom vedea că putem crea funcții puțin mai
"inteligente". Nu vom avea doar o succesiune de instrucțiuni care se execută tot
timpul în același fel, ci vom putea avea comportamente diferite în funcție de modul
în care este apelată o funcție. 
Java - Lecția 07
DE MIHAI SCORȚARU · 22 IUNIE 2015
În cadrul episodului anterior am văzut cum putem crea și apela funcții. Dar acestea
erau foarte simple; practic, erau o înșiruire de instrucțiuni care, eventual, ar putea fi
apelate de mai multe ori. Vom vedea acum că putem face mai multe.

Să considerăm următoarea secvență:

1 int nr = 2457;
2 if (nr % 2 == 0) {
3   System.out.println("Număr par");
4 } else {
5   System.out.println("Număr impar");
6}
Verificăm dacă un număr este par și afișăm un mesaj corespunzător, după caz.
Verificarea se face simplu: numerele pare se împart exact la 2 (restul împărțirii la
doi este zero), iar cele impare nu.
În urma executării acestei secvențe, s-ar afișa mesajul Număr impar. Dacă am vrea
să verificăm paritatea altui număr am mofica prima linie, inițializând variabila nr cu
o altă valoare.
Am putea pune acest cod într-o funcție. Am văzut că uneori e mai bine așa...
Funcția noastră ar putea arăta astfel:

1 private static void verificareParitate() {


2   int nr = 2457;
3   if (nr % 2 == 0) {
4     System.out.println("Număr par");
5   } else {
6     System.out.println("Număr impar");
7   }
8}
Acum putem să o apelăm de mai multe ori; dar, nu facem decât să verificăm de câte
ori vrem paritatea aceluiași număr ( 2457 dacă nu-l schimbăm). Nu pare foarte
util...
Dar, cum ar fi dacă am putea să verificăm paritatea oricărui număr am dori. Nu ar fi
frumos ca atunci când apelăm funcția să putem preciza și care este numărul a cărui
paritate vrem să o verificăm?

Din fericire este posibil. Vă amintiți de acele ciudate parenteze care trebuie
adăugate și când definim și când apelăm funcția? Vom vedea acum la ce sunt
bune... În momentul în care apelăm funcția, putem să precizăm anumite valori sau
variabile, pe care le punem între acele paranteze; dacă sunt mai multe, le separăm
prin virgule. Ele poartă denumirea de argumente ale apelului.
În situația noastră, am vrea să verificăm paritatea anumitor numere: apelurile
noastre ar putea arăta așa:

1 verificareParitate(2457);
2 verificareParitate(47);
3 verificareParitate(0);
4 verificareParitate(a);
Avem patru apeluri. În urma executării primelor două s-ar afișa
textul Număr impar, pentru al treilea s-ar afișa textul Număr par, iar textul afișat
pentru ultimul depinde de valoarea curentă a variabilei a.
Dar, așa cum arată funcția noastră acum, ea nu ia în seamă nicio eventuală valoare
care însoțește apelul. Dar, are și ea acele paranteze care par inutile. Probabil ați
ghicit, putem pune aici ceva. Practic, putem face în așa fel încât valorile
argumentelor apelului să fie disponibile. Pentru aceasta avem așa-
numiții parametri ai funcției. Ei seamănă cu niște variabile: au tip și denumire.
Putem modifica foarte ușor funcția noastră astfel încât ea să aibă un parametru:

1 private static void verificareParitate(int nr) {


2   if (nr % 2 == 0) {
3     System.out.println("Număr par");
4   } else {
5     System.out.println("Număr impar");
6   }
7}
Dacă funcția are mai mulți parametri, sunt separați și ei prin virgule.

De multe ori denumirile de argument și parametru nu sunt folosite corect. Veți auzi
sau vedea de multe ori spunându-se că apelul are parametri sau funcția are
argumente. Noțiunile au ajuns să fie aproape interschimbabile. De fapt, nici nu ar
prea au de ce să fie diferite. Dar, strict vorbind, funcțiile au parametri și apelurile au
argumente.

În Java, tipurile și numărul argumentelor trebuie să se potrivească. Așadar, pentru


noua versiune a funcției, următoarea apeluri nu sunt corecte:

1 verificareParitate(2, 3);
2 verificareParitate("text");
3 verificareParitate();
Când apelăm funcția, putem avea orice argument care este compatibil cu tipul
argumentului; am văzut că putem folosi valori sau variabile; dar, putem avea și
expresii, atâta timp cât tipul rezultatului este compatibil. Următoarea secvență este
corectă:

1 verificareParitate(2 + 3);
2 int nr = 2457;
3 verificareParitate(nr + 47);
4 bool exista = true;
5 verificareParitate(exista ? nr : 13);
Dacă privim cu atenție, ne dăm seama că foloseam apeluri cu argumente încă de la
primul episod. Să revenim la primul program pe care l-am scris în Java:
1 /* package whatever; // don't place package name! */
2
3 import java.util.*;
4 import java.lang.*;
5 import java.io.*;
6
7 /* Name of the class has to be "Main" only if the class is public. */
8 class Ideone
9 {
10   public static void main (String[] args) throws java.lang.Exception
11   {
12     System.out.println("Gazeta de Informatică");
13   }
14 }
În linia 12 vedeți ceva ce seamănă foarte mult cu un apel de funcție; aceasta ar
fi System.out.println, iar argumentul ar fi "Gazeta de Informatică". Este într-adevăr
un apel de funcție; nu apelăm o funcție pe care am creat-o noi, ci una care există
deja în Java. Această funcție afișează la ieșire un mesaj pe care îl primește ca
parametru.
Mai trebuie precizat faptul că denumirea funcției este doar println (nu pot fi folosite
puncte în denumirile funcțiilor); System și out sunt altceva și nu vom intra în detalii
acum fiindcă nu sunt relevante (cel puțin nu în acest moment).

Va urma
Deocamdată am transmis funcției informații din exterior. În episodul următor vom
vedea cum putem comunica și în sens invers; funcțiile pot și ele genera anumite
valori pe care să le comunice apelantului.

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