8.1.4 Eine get()-Methode für MyArrayList
Als Nächstes wollen wir unsere Klasse um eine get()-Methode erweitern, damit wir die Objekte, die wir in die Liste eingefügt haben, auch wieder auslesen können.
Die Methode MyArrayList.get()
Die Methode get() lässt sich zunächst sehr einfach implementieren:
public Object get(int index)
{
checkIndex(index);
return elementData[index];
}
Zuerst wird der übergebene Index mit checkIndex() überprüft. Ist der Index gültig, kann das Element an dieser Position direkt zurückgegeben werden.
Beim Testen zeigt sich allerdings ein Problem: Greift man mit get() auf den Index size zu, bricht das Programm mit einer Exception ab. Der Fehler liegt aber nicht in get() selbst, sondern in der Prüfmethode, die wir implementiert hatten:
private void checkIndex(int index)
{
if (index < 0 || index > size)
throw new IndexOutOfBoundsException
("index ausserhalb: " + index);
}
Diese Bedingung ist für add(index, element) sinnvoll, denn dort ist index == size ausdrücklich erlaubt: Ein neues Element darf am Ende der Liste eingefügt werden.
Für die Methode get(index) gilt das jedoch nicht. Bei einer Liste mit 5 Elementen sind nur die Indizes 0 bis 4 gültig. Der Index 5 zeigt bereits hinter das letzte gespeicherte Element und ist daher nicht mehr erlaubt. Deshalb erhält get() eine zusätzliche Prüfung:
public Object get(int index)
{
checkIndex(index);
if (index == size)
throw new IndexOutOfBoundsException
("index ausserhalb: " + index);
return elementData[index];
}
Damit bleibt checkIndex() weiter für mehrere Methoden verwendbar, während get() den Sonderfall index == size zusätzlich abfängt.
Unterschiedliche Index-Prüfungen
Ein kritischer Betrachter könnte nun einwenden, ob es sinnvoll ist, in der Klasse MyArrayList eine Methode checkIndex() zu implementieren, die zwar für Methoden wie add() sinnvoll ist, aber nicht für die get()-Methode. Die get()-Methode musste bei unserem bisherigen Vorgehen noch eine eigene zusätzliche Index-Prüfung durchführen.
Eine bessere Lösung wäre es, zwei verschiedene Prüfmethoden zu implementieren:
private void checkElementIndex(int index)
{
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException
("index ausserhalb: " + index);
}
private void checkPositionIndex(int index)
{
if (index < 0 || index > size)
throw new IndexOutOfBoundsException
("index ausserhalb: " + index);
}
Die Methode checkElementIndex() wird für den Zugriff auf vorhandene Elemente verwendet, also zum Beispiel in get(), set() und remove().
Die Methode checkPositionIndex() wird dagegen für Einfügepositionen verwendet, also zum Beispiel in add(index, o).
Die get()-Methode würde nach dieser Änderung dann so aussehen:
public Object get(int index)
{
checkElementIndex(index);
return elementData[index];
}
Kritische Betrachtung
Man könnte sich an dieser Stelle allerdings auch fragen, ob die beiden privaten Methoden checkElementIndex() und checkPositionIndex() für unsere noch relativ kleine Klasse wirklich notwendig sind.
Die eigentlichen Prüfungen bestehen jeweils nur aus einer einzigen if-Anweisung. Für Anfänger kann die Aufteilung auf mehrere Hilfsmethoden den Quelltext daher zunächst sogar komplizierter wirken lassen. Außerdem unterscheiden sich beide Methoden nur in einem kleinen Detail:
index >= size
bzw.
index > size
In einer kleinen Klasse wie der unseren wäre es daher durchaus sinnvoll, die Prüfungen direkt in den jeweiligen Methoden zu implementieren. Der Quelltext wäre dann zunächst leichter verständlich.
Die Auslagerung in eigene private Prüfmethoden hat allerdings auch Vorteile, wie wir gesehen haben. Die Prüfungen müssen nicht mehrfach im Programm wiederholt werden (Redundanz-Vermeidung), die Methodennamen machen den Zweck der jeweiligen Prüfung deutlicher und spätere Änderungen lassen sich einfacher durchführen.
Wir orientieren uns hier daher bereits ein wenig an professionellen Bibliotheksklassen, auch wenn die Lösung für eine so kleine Klasse vielleicht noch etwas aufwendig wirkt. Aber in den folgenden Semestern werden Sie sicherlich viel größere Klassen und Anwendungen entwickeln, und das dann erforderliche professionelle Vorgehen haben wir jetzt schon einmal im Kleinen geübt.
Seitenanfang -
Weiter mit der Erweiterung der Klasse MyArrayList ...