Declararea și inițializarea tablourilor cu doi indiciTabloul bidimensional poate fi declarat în mod asemănător celui unidimensional, dar punând după numele variabilei două perechi de paranteze drepte. Rămâne valabilă și regula că, dacă perechea de paranteze drepte se pune după numele tipului sau al clasei, ea se aplică tuturor variabilelor din declarația respectivă. Fie, de exemplu, următoarele declarații:double u, v[], w[][]; int[] a, b[]; char[][] h1, h2; String ts[][]; Conform acestor declarații: - u este o variabilă simplă de tip double; - v este un tablou unidimensional, iar w un tablou bidimensional, ambele cu componente de tip double; - a este un tablou unidimensional, iar b un tablou bidimensional, ambele cu componente de tip int; - h1 și h2 sunt tablouri bidimensionale cu componente de tip char; - ts este un tablou bidimensional, având drept componente referințe la String. Inițializarea tablourilor bidimensionale se face, de
asemenea, asemănător cu a celor unidimensionale, având însă și unele
trăsături specifice. Iată cum putem introduce în declarațiile de mai sus
inițializări folosind forma cu acolade sau operatorul new: Remarcam ca, la forma de inițializare cu acolade, tabloul bidimensional este tratat ca un tablou (acoladele exterioare) care are drept componente alte tablouri (acoladele interioare). Acestea din urmă reprezintă "liniile" tabloului bidimensional și pot avea lungimi diferite, unele din ele putând avea chiar lungimea zero (în acest caz acoladele respective nu conțin nimic), ca în cazul liniei a doua a tabloului b. La folosirea operatorului new există urmatoarele
posibilități de inițializare: În figura 1 este reprezentată matricea w dupa inițializare.
- Figura 1 - Se observă că variabila w conține numai o referință către un tablou cu trei componente care, la rândul lor, conțin referințe către trei tablouri care conțin cele trei linii ale tabloului bidimensional indicat de variabila w. In aceasta situație, cele trei "linii" ale tabloului bidimensional pot să fie situate în locuri diferite din memorie, fără a mai forma o zonă compactă. În schimb, fiecare "linie" este, în acest caz, un tablou compact, ale cărui componente sunt valori primitive de tip double. Să considerăm acum tabloul
- Figura 2 - Componentele tabloului sunt aici, de fapt, referințe la obiecte din clasa String. La nivel conceptual însă, noi privim acest tablou ca și când ar avea drept componente însăși aceste obiecte. Pentru a le distinge mai ușor, în figura 2 obiectele din clasa String au fost trasate cu culoare albastră. Inițializările de mai sus sunt testate în programul din fișierul Tab2.java. Operații cu tablouri bidimensionaleNumărul de componenteȘtim că fiecărui tablou unidimensional îi este asociată o variabilă length, care are ca valoare "lungimea" tabloului, adică numărul de componente ale acestuia. Ce reprezintă variabila length în cazul unui tablou bidimensional? Sa privim din nou figura 1. Întrucat w.length este numărul de componente din tabloul unidimensional referit de variabila w, înseamnă că el este egal cu numărul de linii al tabloului bidimensional. În schimb, numărul de componente din linia referită de componenta w[i] a tabloului w este dat de variabila w[i].length. De exemplu, numărul de componente din linia de indice 0 este w[0].length. În programul din fisierul Tab2.java se determină astfel numărul de linii și numărul de componente din fiecare linie pentru fiecare din tablourile bidimensionale inițializate în programul respectiv.Referirea la componentele tablouluiPentru a indica o anumită componentă a unui tablou bidimensional, se folosește variabila referință la tablou, însoțită de indicii componentei respective. De exemplu, w[i][j] este componenta situata în linia i și coloana j a tabloului referit de variabila w. Indicii pot fi literali întregi, variabile sau expresii de tip întreg, de exemplu w[2*k-1][j-3]. Referirile la componentele de tablou au fost folosite, de exemplu, în programul din fișierul Tab2.java la afișarea tablourilor. În același program se poate urmări și cum sunt afișate componentele tablourilor, în situația când liniile acestor tablouri au lungimi diferite.Componentele de tablou astfel referite pot fi folosite în
orice expresii din program, la fel ca variabilele simple. Iată doua
exemple de instrucțiuni, în care se folosesc componentele tabloului
bidimensional w: Referirea la tablou și la liniile tablouluiVariabila referință la tablou, neînsoțită de indici, este o referire la întregul tablou. Dacă folosim însa variabila referință la un tablou bidimensional însoțită de un singur indice, aceasta este o referință la o linie a tabloului respectiv. De exemplu, în cazul tabloului bidimensional w, w[i] este o referință la linia i a tabloului indicat de variabila w. Variabilele w și w[i] pot fi folosite și ele în diferite expresii. Astfel s-a procedat mai sus, în expresiile w.length si w[i].length. Să urmărim acum un exemplu, în care se ilustrează folosirea acestor referințe în instrucțiuni de atribuire.Să urmarim programul din fișierul Tab2a.java,
făcând și schemele tablourilor din memorie in diferite etape de
execuție a acestuia. Se fac mai intâi următoarele declarații cu
inițializări de tablouri: Rezultatul aceztor initializari este reprezentat in figura
3.
- Figura 3- Se fac apoi urmatoarele atribuiri: Situatia creată în memorie după această secvență de atribuiri este reprezentată in figura 4.
- Figura 4 - În aceasta figură, pentru a fi urmărite mai ușor, modificarile au fost făcute cu culoare roșie. A fost creat, prin operatorul new, un nou tablou cu trei elemente, care a devenit noua linie a[2]. S-au atribuit valori pentru a[2][0] si a[2][2], iar componenta a[2][1] a rămas la valoarea implicită 0 cu care a fost inițializată. Fosta linie a[3], formată numai dintr-o singură componentă cu valoarea 105, a rămas fără referință și va fi eliminată de către colectorul de reziduuri de memorie. Noua linie a[3] este acum fostul tablou b, iar tabloul unidimensional indicat de variabila referinta b este acum acelasi cu linia a[1]. Toate aceste modificari pot fi verificate executând programul din fișierul Tab2a.java . Conversii de tip la tablouri cu doi indiciRegulile aplicate pentru conversii la tablourile bidimensionale sunt aceleași cu cele pentru tablouri unidimensionale. Să urmărim următorul exemplu, care este testat în programul din fișierul Tab2b.java. Fie declarațiile:Object ob1, ob2, tob2[][]; int ti1[][]={{0,1},{10,11,12,13},{20,21,22}},ti2[][]; String ts[][]={{"aa","ab"},{"ba","bb","bc"},{"ca","cb"}},ts1[][]; Cu aceste declarații, următoarele atribuiri Numărul de linii al tabloului indicat de variabila referință ob1 este ((int[][])ob1).length, iar numarul de componente din linia i a aceluiasi tablou este ((int[][])ob1)[i].length. De asemenea, componenta situată în linia i și coloana j este((int[][])ob1)[i][j]. Să încercăm acum atribuirea ti2=(int[][])ob2; În acest caz, compilatorul nu poate sesiza eroarea, deoarece în momentul compilării nu are informație despre adevarata clasa căreia îi aparține obiectul indicat de variabila ob2. În schimb, la execuție se constată că obiectul indicat de ob2 aparține clasei String[][], în timp ce variabila ti1 apartine clasei int[][], așa că se va genera excepția ClassCastException. |
- Figura 5 -
În programul din fișierul TabEterogen.javase construiește această structură de date eterogenă și se afișează unele dintre componentele ei.