5.4 Arrays Oft müssen viele Werte gleichen Typs gespeichert werden. Idee: Lege sie konsekutiv ab! Greife auf einzelne Werte über ihren Index zu! Feld: Index: 17 3-2 9 0 1 0 1 2 3 4 5 Harald Räcke 114/656
Beispiel 1 i n t [ ] a ; // Deklaration 2 i n t n = read ( ) ; 3 4 a = new i n t [ n ] ; // Anlegen des Felds 5 i n t i = 0; 6 while ( i < n ) { 7 a [ i ] = read ( ) ; 8 i = i +1; 9 } Einlesen eines Feldes 5.4 Arrays Harald Räcke 115/656
Beispiel type[] name; deklariert eine Variable für ein Feld (array), dessen Elemente vom Typ type sind. Alternative Schreibweise: type name[]; Das Kommando new legt ein Feld einer gegebenen Größe an und liefert einen Verweis darauf zurück: a Alles was mit new angelegt wird, ist vorinitialisiert. Referenztypen zu null, Zahltypen zu 0, boolean zu false. Man kann auch leere Felder anlegen: new int[0]. a = new int[6]; a 0 0 0 0 0 0 5.4 Arrays Harald Räcke 116/656
Was ist eine Referenz? Eine Referenziable speichert eine Adresse; an dieser Adresse liegt der eigentliche Inhalt der Variablen. a: Adresse. 0000 0127 0000 0128 Inhalt. 0000 012C a 4 3 0 9 0000 0129 0000 012A Wir können die Referenz nicht direkt manipulieren (nur über den new-operator, oder indem wir eine andere Referenz zuweisen). 0000 012B 0000 012C 0000 012D 0000 012E 0000 0004 0000 0003 0000 0000 Eine Referenz zeigt daduch nie auf einen beliebigen Ort im Speicher; sie zeigt immer auf ein gültiges Objekt oder auf das null-objekt. Wir geben üblicherweise nie den Wert einer Referenziablen an, sondern symbolisieren diesen Wert durch einen Pfeil auf die entsprechenden Daten. 0000 012F 0000 0130. 0000 0009.
5.4 Arrays Der Wert einer Feld-Variable ist also ein Verweis!!! int[] b = a; kopiert den Verweis der Variablen a in die Variable b: a Insbesondere beim Kopieren von Feldern (und anderen Referenztypen) muss man sich dessen immer bewusst sein. a int[] b = a; b Alle nichtprimitive Datentypen sind Referenzentypen, d.h., die zugehörige Variable speichert einen Verweis!!! 5.4 Arrays Harald Räcke 118/656
5.4 Arrays Die Elemente eines Feldes sind von 0 an durchnummeriert. Die Anzahl der Elemente des Feldes name ist name.length. Auf das i-te Element greift man mit name[i] zu. Bei jedem Zugriff wird überprüft, ob der Index erlaubt ist, d.h. im Intervall {0,..., name.length-1} liegt. Liegt der Index außerhalb des Intervalls, wird eine ArrayIndexOutOfBoundException ausgelöst ( Exceptions). Sie sollten beim Programmieren möglichst nie diese Exception bekommen. In anderen Sprachen (z.b. C/C++) gibt es aus Effizienzgründen keine Überprüfung. Wenn Sie in einer solchen Sprache einen solchen Fehler verursachen, ist der sehr schwierig zu finden. 5.4 Arrays Harald Räcke 119/656
Mehrdimensionale Felder Java unterstützt direkt nur eindimensionale Felder. ein zweidimensionales Feld ist ein Feld von Feldern... a a = new int[5][6]; a
Der new-operator So etwas wie new int[3][][4] macht keinen Sinn, da die Größe dieses Typs nicht vom Compiler bestimmt werden kann. symbol name types L/R level new new Typ, Konstruktor links 1 Erzeugt ein Objekt/Array und liefert eine Referenz darauf zurück. 1. Version: Erzeugung eines Arrays (Typ ist Arraytyp) new int[3][7]; oder auch new int[3][]; (ein Array, das 3 Verweise auf int enthält) new String[10]; new int[]{1,2,3,}; (ein Array mit den ints 1, 2, 3) 2. Version: Erzeugung eines Objekts durch Aufruf eines Konstruktors String s = new String("Hello World!"); Was genau ein Konstruktor ist kommt später.
Der Index-Operator symbol name types L/R level [] index array, int links 1 Zugriff auf ein Arrayelement. 5.4 Arrays Harald Räcke 122/656
x = a [ 3 ] [ 2 ]
x = a [ 3 ] [ 2 ]
x = a [ 3 ] [ 2 ]
x = [ ] [ 2 ] a 3
x = [ ] [ 2 ] a 3
x = [ ] [ ] 2 a 3
x = [ ] [ ] 2 a 3
= x [ ] [ ] 2 a 3
= x [ ] [ ] 2 a 3 x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] [ ] 2 a 3 x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] 2 a 3 x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] 2 a 3 x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] 2 a 3, int[][] x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] 2 a 3, int[][] x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] 2 a 3, int[][] 3, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] 2 a 3, int[][] 3, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int, int[] [ ] 2 a 3, int[][] 3, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int, int[] [ ] 2 a 3, int[][] 3, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] a 3, int[][], int[] 3, int val 2 2, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] a 3, int[][], int[] 3, int val 2 2, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] a 3, int[][], int[] 3, int val 6, int 2 2, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] a 3, int[][], int[] 3, int val 6, int 2 2, int val x 2 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
= x [ ] 2, int [ ] a 3, int[][] 6, int val, int[] 3, int val 6, int 2 2, int val x 6 a 1 2 3 4 5 6 0 9 8 3 4 4 9 7 4 6 0 6 2 5 6 4 2 3 5 0 1 2 8 3
Der. -Operator symbol name types L/R level. member access Array/Objekt/Class, Member links 1 Zugriff auf Member. Beispiel: x = new int[2][4].length x hat dann den Wert 2. 5.4 Arrays Harald Räcke 124/656
Beispiel: new int[2][4].length Das Parsing für den new-operator passt nicht in das Schema: new int [ 2 ] [ 4 ]. length Beachte den Unterschied zwischen new int[2][3] und (new int[2])[3]. Bei letzterem ist das zweite Klammerpaar ein Index-Operator während es beim ersten Ausdruck zum Typ gehört.
Beispiel: new int[2][4].length Das Parsing für den new-operator passt nicht in das Schema: new int [ 2 ] [ 4 ]. length Beachte den Unterschied zwischen new int[2][3] und (new int[2])[3]. Bei letzterem ist das zweite Klammerpaar ein Index-Operator während es beim ersten Ausdruck zum Typ gehört.
Beispiel: new int[2][4].length Das Parsing für den new-operator passt nicht in das Schema: new int [ 2 ] [ 4 ]. length Beachte den Unterschied zwischen new int[2][3] und (new int[2])[3]. Bei letzterem ist das zweite Klammerpaar ein Index-Operator während es beim ersten Ausdruck zum Typ gehört.
Beispiel: new int[2][4].length Das Parsing für den new-operator passt nicht in das Schema: new. length int int[2][4] [ 2 ] [ 4 ] Beachte den Unterschied zwischen new int[2][3] und (new int[2])[3]. Bei letzterem ist das zweite Klammerpaar ein Index-Operator während es beim ersten Ausdruck zum Typ gehört.
Beispiel: new int[2][4].length Das Parsing für den new-operator passt nicht in das Schema: new. length int int[2][4] [ 2 ] [ 4 ] Beachte den Unterschied zwischen new int[2][3] und (new int[2])[3]. Bei letzterem ist das zweite Klammerpaar ein Index-Operator während es beim ersten Ausdruck zum Typ gehört.
Beispiel: new int[2][4].length Das Parsing für den new-operator passt nicht in das Schema:. new length int int[2][4] [ 2 ] [ 4 ] Beachte den Unterschied zwischen new int[2][3] und (new int[2])[3]. Bei letzterem ist das zweite Klammerpaar ein Index-Operator während es beim ersten Ausdruck zum Typ gehört.
Arrayinitialisierung 1. int[] a = new int[3]; a[0] = 1; a[1] = 2; a[2] = 3; 2. int[] a = new int[]{ 1, 2, 3}; 3. int[] a = new int[3]{ 1, 2, 3}; 4. int[] a = { 1, 2, 3}; 5. char[][] b = { { a, b }, new char[3], {} }; 6. char[][] b; b = new char[][]{ { a, b }, new char[3], {} }; 7. char[][] b; b = { { a, b }, new char[3], {} }; 5.4 Arrays Harald Räcke 126/656