Am văzut până acum că trebuie să declarăm variabilele înainte să le folosim. Dar, oare le putem folosi oriunde? Nu chiar...
Să considerăm următorul program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Test { public static void test () { int n = 2457; if (n % 2 == 0) { System.out.println("Număr par"); } else { System.out.println("Număr impar"); } } public static void main (String[] args) { test(); System.out.println(n); } } |
Poate ne-am aștepta ca totul să fie în regulă, dar nu e așa. Primim o eroare care ne spune că variabila n din linia 13 nu este cunoscută. Ar părea că am declarat această variabilă în linia 3. Dar, această declarație a fost făcută în interiorul funcției test și e valabilă doar acolo.
Spunem că o variabilă este vizibilă doar acolo unde este declarată. Evident, ea poate fi folosită doar acolo unde este vizibilă. Spunem că locul în care poate fi văzută o variabilă este domeniul de vizibilitate al variabilei.
Am văzut că o variabilă declarată într-o funcție nu poate fi utilizată în afara funcției respective. Dar, e mai complicat decât atât. De fapt, o variabilă este vizibilă doar în interiorul blocului de instrucțiuni în care a fost declarată. Următorul program nu este nici el corect:
1 2 3 4 5 6 7 8 9 10 |
public class Test { public static void main (String[] args) { int n = 2457; if (n % 2 == 0) { int k = 47; System.out.println(k % 10); } System.out.println(k); } } |
De data aceasta eroarea apare în linia 8, deși variabila k a fost declarată în linia 5.
Dacă o variabilă nu este vizibilă într-un anumit bloc de instrucțiuni, o putem declara. Ar putea părea că am declarat o variabilă de mai multe ori, dar trebuie să luăm în considerare faptul că domeniile de vizibilitate sunt diferite. Următorul program este corect:
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Test { public static void main (String[] args) { int n = 2457; if (n % 2 == 0) { int k = 47; System.out.println(k % 10); } else { int k = 13; System.out.println(k % 2); } } } |
Practic avem două variabile k; prima există în blocul de instrucțiuni dintre liniile 4 și 7, iar a doua în blocul dintre liniile 7 și 10.
Trebuie să avem grijă ca domeniile de vizibilitate a două variabile cu același nume să nu se suprapună. De cele mai multe ori nu este permis; uneori este posibil, dar trebuie să fim atenți.
Am putea încerca să înlocuim în linia 3 n cu k. Nu mai este corect; vom avea erori pe liniile 5 și 8 care precizează că variabila k este deja definită.
Să vedem acum un exemplu mai interesant:
1 2 3 4 5 6 7 8 9 10 |
public class Test { public static void test(int n) { int n = 47; System.out.println(n); } public static void main (String[] args) { test(2457); } } |
Nu este corect nici așa ceva; parametrul n este vizibil în cadrul funcției test, deci corpul acestei funcții nu poate conține o declarație a unei variabile cu același nume fiindcă domeniile de vizibilitate s-ar suprapune.
Am văzut că, dacă au domenii de vizibilitate diferite, două variabile sunt diferite chiar dacă au aceeași denumire. Să vedem mai exact ce înseamnă acest lucru:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class Test { public static void test() { int n; n = 47; System.out.println(n); } public static void main (String[] args) { int n = 2457; test(); System.out.println(n); } } |
Avem o variabilă n a cărei valoare este 2457. Apelăm funcția test; în cadrul acesteia avem o altă variabilă n cu valoarea 47 și scriem valoarea acesteia. Execuția funcției se încheia și urmează scrierea variabilei n; se va scrie 2457, fiindcă variabila din interiorul funcției nu este vizibilă în afara funcției și atribuirea din linia 4 afectează doar variabila declarată în linia 3, nu și pe cea declarată în linia 9.
Trebuie să reținem faptul că orice instrucțiune care folosește o variabilă o folosește pe cea vizibilă, chiar dacă în alte locuri există variabile cu același nume. Să vedem un exemplu mai interesant:
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Test { public static void test(int n) { n++; System.out.println(n); } public static void main (String[] args) { int n = 2457; test(n); System.out.println(n); } } |
Vom vedea că în urma execuției instrucțiunii din linia 4, este scrisă valoarea 2458, dar în urma execuției instrucțiunii din linia 10, este scrisă valoarea 2457.
Avem o variabilă n definită în linia 8 și inițializată cu valoarea 2457. Aceasta este transmisă ca argument al apelului funcției test. În linia 3 valoarea parametrului funcției test este incrementată. Dar, deja avem o altă variabilă (parametrul); incrementarea se aplică doar asupra ei. Noua valoare este tipărită și execuția funcției test se încheie. Variabila definită în linia 8 nu a fost afectată de incrementarea din linia 3; ca urmare, în momentul executării instrucțiunii din linia 10, valoarea sa este tot 2457.
Există mecanisme prin care modificările aduse unui parametru al unei funcții să nu se piardă în momentul în care se încheie execuția funcției respective, dar vom reveni asupra acestui aspect la momentul oportun.
Situația este aceeași dacă variabila transmisă ca argument ajunge să devină un parametru cu alt nume. Efectul execuției următorului program este același:
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Test { public static void test(int k) { k++; System.out.println(k); } public static void main (String[] args) { int n = 2457; test(n); System.out.println(n); } } |
Va urma
Am văzut până acum cum putem avea instrucțiuni care să se execute sau nu (folosind instrucțiuni condiționale). Am văzut de asemenea cum putea avea instrucțiuni care sunt executate de mai multe ori (folosind apeluri multiple de funcții). Dar, trebuie să efectuăm câte un apel de fiecare dată când doream să executăm o funcție. În următorul episod vom introduce conceptul de buclă; vedea cum vom putea executa anumite instrucțiuni de mai multe ori, atâta timp cât o anumită condiție este îndeplinită.