Java: Methoden
Willemers Informatik-Ecke
Eine Methode fasst den Ablauf mehrerer Anweisungen zusammen. Methoden werden in anderen Programmiersprachen Funktionen oder Routinen bezeichnet.

Anatomie einer Methode

Wird eine Folge von Befehlen mehrfach verwendet, schreibt man sinnvollerweise eine Methode. Um sie später aufrufen zu können, erhält sie einen Namen. In Klammern folgen die Parameter. Diese sehen aus wie durch Kommata getrennte Variablendeklarationen. Eine Methode kann auch einen Wert zurückgeben. Dessen Typ steht vor dem Methodennamen. Ist dies soweit fertig, kann in geschweiften Klammern der Block von Anweisungen folgen, die bei Aufruf der Methode abgearbeitet werden sollen.

.

Methoden sind Aktionen, insofern sollte man Verben als Methodennamen vergeben. Methoden mit booleschen Rückgabewerten beginnt man gern mit "ist" oder "hat" oder ihren englischen Gegenstücken. Nach Konvention werden Methodennamen kleingeschrieben.

Eine Methode wird über ihren Namen und ihre Parameter aufgerufen. Falls die Methode einen Rückgabewert hat, kann dieser als Ausdruck verwendet werden, also ausgegeben oder einer Variablen zugewiesen werden.

public class MethodenTest {

    static void sagDochWas() {
        System.out.println(“Hallo”);
    }

    public static void main(String[] args) {
        sagDochWas();
        sagDochWas();
    }
}

void bedeutet, dass die Methode keine Werte zurückliefert. Die leere Klammer zeigt an, dass die Methode keine Parameter besitzt. Sie wird durch Nennung des Namens und der Parameter aufgerufen. Im Beispiel wird sie zweimal hintereinander aufgerufen. Also sollte auf dem Bildschirm zweimal untereinander das Wort Hallo erscheinen.

Das Wort static ist notwenig, wenn die Methode wie hier von einer anderen Methode aufgerufen wird, die ebenfalls static ist.

Lokale Variablen

Innerhalb einer Methode können lokal Variablen definiert und verwendet werden. Diese sind von außen nicht sichtbar und kollidieren auch nicht mit dem Namen von Variablen des Aufrufers. Die Variable stirbt am Ende der Methode.

Parameter und Rückgabewert

Einer Methode können über die Parameter Werte übergeben werden. Ein Parameter ähnelt dabei einer Variablendefinition. Mehrere Parameter werden durch Kommata getrennt.

Beim Aufruf müssen die Parameter typkompatibel in der gleichen Reihenfolge vollständig bedient werden.

Die Übergabe selbst ähnelt einer Zuweisung. Der übergebene Wert wird in die Parametervariable kopiert. Die Methode kann diese Variable wie eine lokale Variable behandeln. Die übergebene Variable des Aufrufers kann aus der Methode nicht verändert werden.

Anders verhält es sich, wenn Referenzen übergeben werden. Zwar werden diese ebenfalls kopiert. In diesem Fall verweist aber die Parametervariable auf den Speicher, den auch der Aufrufer verwendet. Wird der referenzierte Wert innerhalb der Methode verändert, ändert sich dieser auch für den Aufrufer.

Im folgenden Beispiel wird eine Methode verdoppeln definiert und in main aufgerufen.

public class MethodenTest {

    static double verdoppeln(double wert) {
        return 2*wert;
    }

    public static void main(String[] args) {
        double zahl = 0;
        zahl = verdoppeln(5.0);
        System.out.println(zahl);
    }
}

Der Befehl return bewirkt, dass das Ergebnis des nachfolgenden Ausdrucks an den Aufrufer zurückgegeben wird. Es kann immer nur ein Wert zurückgegeben werden. Ist es erforderlich mehrere Werte aus der Methode zurückzugeben, muss ein Klassenobjekt oder ein Array verwendet werden.

Methoden überladen

Eine Methode wird durch ihren Namen und die Parameter eindeutig. Diese Kombination nennt man eine Signatur. Es kann also mehrere Methoden gleichen Namens geben, wenn sie sich nur anhand ihrer Parameter signifikant unterscheiden.

Java erkennt anhand des Aufrufparameters, welche der Methoden aufgerufen werden soll.

Der Aufruf von System.out.println ist ein Beispiel für eine überladene Methode. Die Methode kann sowohl mit einem String als auch mit einer Zahl aufgerufen werden, weil sie für beide Parameter definiert wurde.

Rekursion

Eine Rekursion ist eine Methode, die sich selbst aufruft. Das tut sie so lange, bis eine Bedingung greift, die einen weiteren Selbstaufruf verhindert. Insofern ähnelt sie einer Schleife.

Das folgende Beispiel erzeugt, wie der Name der Methode schon vermuten lässt, einen Countdown. Die Methode gibt den übergebenen Wert auf dem Bildschirm aus und ruft sich selbst mit dem um 1 verminderten Parameter auf.

countDown(int n) {
  if (n>0) {
    System.out.println(n);
    countDown(n-1);
  }
}
// ...
countDown(10);

Irgendwann ist der Parameter 0 und die Abfrage greift nicht mehr. Stattdessen kehrt die Methode zu ihrem Aufrufer zurück, der eben sie selbst ist. Aber dort passiert nichts mehr. Sie läuft auch hier auf das Methodenende. Das geschieht so lange, bis sie zu ihrem Aufrufer zurückkehrt.

Umgekehrt

Tauscht man die beiden Zeilen hinter der Abfrage aus, zählt die Mehode von 1 bis 10. Das liegt daran, dass nun die Methode die Ausgabe erst erreicht, wenn sie bis zum Ende abgestiegen ist. Erst wenn der Parameter 0 ist, kehrt die Methode zurück, springt hinter den Aufruf und erreicht dort System.out.println. Damit wird dann 1 ausgegeben. Der Rücksprung kommt in die Methode, wo n noch 2 war und so geht es weiter.

countUp(int n) {
  if (n>0) {
    countUp(n-1);
    System.out.println(n);
  }
}
// ...
countDown(10);

Baumstrukturen

Nun ist es Unsinn, mit Rekursionen zu zählen. Das können Schleifen sehr viel effizienter und übersichtlicher. Es gibt aber Situationen, die von Rekursionen optimal gelöst werden und bei denen Schleifen versagen. Das gilt beispielsweise immer dann, wenn man es mit Baumstrukturen zu tun hat.

Eine solche Baumstruktur liegt auch bei der Lösung der Türme von Hanoi vor, die von dem folgenden Programm gelöst werden. Hier wird zunächst vom Ausgangspunkt zum freien Stock rekursiv bewegt. Dann wird der Zug angezeigt. Anschließend wird vom freien Stock zum Zielpunkt gezogen. Das Prinzip der Rekursion ist es, die Arbeit vor sich herzuschieben.

public class TuermeVonHanoi {
    static void ziehe(int von, int nach, int scheibenZahl) {
        if (scheibenZahl > 0) {
            int frei = 6 - von - nach;
            ziehe(von, frei, scheibenZahl - 1);
            System.out.print(von);
            System.out.print(" - ");
            System.out.println(nach);
            ziehe(frei, nach, scheibenZahl - 1);
        }
    }

    public static void main(String[] args) {
        ziehe(1, 3, 3); // von 1 nach 3, 3 Scheiben
    }
}
Einsatzgebiet sind alle Arten von Baumstrukturen. Auch ein Straßennetz gehört zu diesem Bereich. Ein Navi verwendet also im großen Umfang Rekursionen.

Auch alle Formen von Klammern werden rekursiv ausgewertet. Dazu gehört der Compilerbau sowie die Simulation eines Taschenrechners.