# Array; java.lang.ArrayIndexOutOfBoundsException



## xyt4n (27. Sep 2012)

Hallo,

ich muss eine etwas längere Aufgabe erledigen, komme aber an etwas simplen nicht weiter.
Ich möchte zu erst mal ein Array ausgeben können. Jedesmal kommt bei der Ausführung der Fehler, der im Titel steht. Ich finde einfach nicht den Fehler.. Hier mein Skript:


```
import org.riediger.jconsole.JConsole;

public class Matrizen {
	public static void readIntArray() {
		int zeilenzahl = JConsole.readInt("Wieviele Spalten sollen es sein?:");
		int spaltenzahl = JConsole.readInt("Wieviele Zeilen sollen es sein?:");
		int array[][] = new int[zeilenzahl][spaltenzahl];

		for (int i = 0; i <= zeilenzahl; i++) {
			for (int j = 0; j <= spaltenzahl; j++) {
				System.out.print(array[i][j] = 0);
			}

		}
	}

	public static void main(String[] args) {
		JConsole.start();
		readIntArray();
	}
}
```


----------



## BRoll (27. Sep 2012)

Deine Schleifen sind auch zu lange,
wenn du mit der Variable zeilenanzahl die Arraygröße einstellst,
ist das größte Feld [zeilenanzahl-1]  weils ja mit 0 beginnt.

Also müsste es heißen:


```
for (int i = 0; i < zeilenzahl; i++) {
            for (int j = 0; j < spaltenzahl; j++) {
                System.out.print(array[i][j] = 0);
            }
```

Deshalb gibts auch einArray Out of Bounds, also außerhalb der Feldgröße.

mfg BRoll


----------



## xyt4n (27. Sep 2012)

Danke! Diesen Fehler hab ich eigentlich ausgeschlossen. Ich dachte die Variable Zeilenzahl ist die "Indexlänge" und nicht die Länge des Arrays, oder wie soll ich das verstehen?

Wenn ich den ersten Index will, heißt es doch array[0][0]. 

Ich bin ehrlich gesagt jetzt verwirrt.???:L


----------



## BRoll (27. Sep 2012)

Sagen wir mal zeilenanzahl =5.

Und wenn du ein Array   zb.  int[] test=new int[5]; machst,
dann hat der die Felder: {0,1,2,3,4} = 5 Stück.
Du darfst dich da nicht verwirren lassen mit der 0,
wenn ein Array  5 Felder groß ist, ist der höchste Index die 4.

Aber wenn du die Länge von einem Array ausliest, bekommst
du dann wieder die 5, also die Felderanazhl != Höchster Index,
sondern Felderanzahl = Höchster Index+1; 

Also würde test.length; 5 zurückgeben.
Trotzdem gibts das Feld tes[5] nicht!

Ich hoffe du hasts jetzt verstanden 

mfg BRoll


----------



## Bernd Hohmann (27. Sep 2012)

Das ist immer wieder verwirrent, besonders wenn man zusätzlich mit Sprachen arbeitet wo der erste Arrayindex die 1 ist statt 0 wie in Java.

"int test[]=new int[1]" erzeugt ein Array der Länge "1", das erste und einzige Element darin ist aber "test[0]"

"int test[]=new int[5]" erzeugt ein Array der Länge "5", die belegbaren Elemente sind 0,1,2,3,4 (zähl die Anzahl der Ziffern, es sind genau 5 Stück).

Daher Arrays immer bis "i<array.length" bzw. Listen bis "i<liste.size()" iterieren.

Bernd


----------



## xyt4n (27. Sep 2012)

Ich bin jetzt ein wenig weiter, aber komme schon wieder nicht voran. 
Ich glaube das Problem ist, dass die eine Methode nicht die einzelnen Elemente erkennt, die ich in einer anderen Methode bestimmt habe.
Dabei habe ich gelernt, dass arrays "global" sind.

Hier das Skript:


```
import org.riediger.jconsole.JConsole;

public class Matrizen {
public static void printArray(int[] array){
		
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array.length; j++) {
				System.out.print(array[i][j]+"\t"); //Fehler
			}
			System.out.println();
		}
		
	}
	
	public static void einheitsArray() {
		int n = JConsole.readInt("Welche Einheitsgröße?:");
		int array[][] = new int[n][n];

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				array[i][j] = 0;
			}
		}
		for (int i = 0; i < n; i++) {
			array[i][i] = 1;
		}
	}

	public static void main(String[] args) {
		JConsole.start();
		einheitsArray();
		printArray(array); //Fehler
	}
}
```

Wird es nicht gern gesehen, wenn man viele Themen am Tag eröffnet? Ich muss vor meinem Studium mir grundlegende Sachen in Java beibringen und lerne fast den ganzen Tag. Dann habe ich natürlich mehrmals Probleme...


----------



## BRoll (27. Sep 2012)

Ne das kann ja garnicht funktionieren.

Wie soll die main methode den array kennen der erst in der
einheitsArray() Methode erstellt wird?

Da gibts zwei Möglichkeiten:

Entweder du machst den Array als Klassenvariable,
dann sehen ihn alle Methoden dort.

Oder du gibst den Array als rückgabewert an die main weiter.

Umgesetzt würde das so aussehen:

Variante 1:


```
static int array[][]; //Jetzt ists eine klassenvariable weil es in keiner Methode erst erstellt wird.

 public static void einheitsArray() {
        int n = JConsole.readInt("Welche Einheitsgröße?:");
        array= new int[n][n];//wird zwar hier belegt, wurde aber schon definiert von der klasse
 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                array[i][j] = 0;
            }
        }
        for (int i = 0; i < n; i++) {
            array[i][i] = 1;
        }
    }

... der Rest gleich
```

Oder eben mit Rückgabewert:


```
public static int[][] einheitsArray() {
        int n = JConsole.readInt("Welche Einheitsgröße?:");
        int array[][] = new int[n][n];
 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                array[i][j] = 0;
            }
        }
        for (int i = 0; i < n; i++) {
            array[i][i] = 1;
        }
    return array;
    }

 public static void main(String[] args) {
        JConsole.start();
     int[][] array=   einheitsArray();
        printArray(array); 
    }
```

Wie du siehst  haben bei der zweiten Variante beide Methoden den Array sogar mit gleichem namen, aber beide kennen sich nicht. dh. sie werden nur beim ausführen der Methode erstellt und danach wieder verworfen. 

mfg BRoll


----------



## xyt4n (27. Sep 2012)

Danke! Hab gerade ne Menge gelernt, da ich noch vollkommen unsicher mit Methoden, Klassen und Wertübergabe bin.


----------



## Bernd Hohmann (27. Sep 2012)

xyt4n hat gesagt.:


> Dabei habe ich gelernt, dass arrays "global" sind.



Wer sagt denn sowas? Ich befürchte, dass Du das mit dem "call by reference" für arrays verwechselst:


```
String teststring=new String("Hallo Welt"); // äquivalent zu teststring="Hallo Welt";
testmethode(test); // by value
System.out.println(teststring); // "Hallo Welt"

static void testmethode(String t) {
   t=new String("Hallo Dorf"); // äquivalent zu t="Hallo Dorf"
}
```

ABER:


```
String teststring[]=new String[1];
teststring[0]=new String("Hallo Welt"); // teststring[0]="Hallo Welt";
testmethode(test): // by reference
System.out.println(teststring[0]); // "Hallo Dorf"

static void testmethode(String t[]) {
   t[0]=new String("Hallo Dorf");
}
```

Im ersten Fall wird in "testmethode" dem Objekt "t" ein neues Objekt zugewiesen, was aber ausserhalb der Methode keinen interessiert. Im zweiten Fall wird quasi das "innere" des Objektes "t" verändert was sich dann nach aussen durchschlägt. Wie für Array gilt das dann auch für sowas wie Listen etc.. - solange man nur in den Innereien herumwerkelt und Werte ändert, ist das auch ausserhalb sichtbar. Wenn in der Methode das Objekt neu definiert wird, interessiert das nur innerhalb der Methode - also alles mit "new" auf den Übergabeparameter ist nicht ausserhalb der Methode sichtbar.

Wenn man mal schaut, wie das verarbeitet wird kommt man auch schnell dahinter: Übergeben an die Methode wird nur die Information "Die Daten stehen im Speicherblock 47110815" (also eine Referenz), wenn da mit "new" gearbeitet wird dann wird auch ein neuer Speicherblock und damit eine neue Referenz erzeugt - die aber nicht ans Hauptprogramm zurück übergeben wird. Wenn aber nur der Inhalt des Speicherblocks "47110815" geändert wird bleibt die Welt in Ordnung und auch der Aufrufer bekommt die Änderung mit.

Bernd


----------



## Landei (27. Sep 2012)

xyt4n hat gesagt.:


> Danke! Diesen Fehler hab ich eigentlich ausgeschlossen.



Ich finde es immer wieder drollig, wenn der Compiler klipp unhd klar sagt, was der Fehler ist, und dann jemand meint, dass das einfach nicht sein kann. Bei einem Stück Software, das von Millionen Menschen verwendet wird, und an dem seit 17 Jahren herumgefeilt wird, fällt ja so eine Kleinigkeit wie eine falsche Fehlermeldung auch nicht sonderlich auf...


----------

