1.10 Methoden

Motivation

Bisher waren unsere Java-Programme stets so aufgebaut:

public class <Programmname> {

   public static void main(String[] args) {
      
      <Anweisungen>

   }

}

Bei den Anweisungen – also dem eigentlichen Programm – kann es häufig passieren, dass gewisse Arbeitsschritte an verschiedenen Stellen nötig sind. In solchen Situationen kopiert man dann ganz gerne einen Teil des Programmtextes und fügt ihn an anderer Stelle noch einmal ein. Dadurch wird der Programmtext aber insgesamt sehr lang und auch schnell unübersichtlich. Daher schauen wir uns nun eine elegantere Möglichkeit an.

Methoden ohne Rückgabewert

Die Videoversion dieses Abschnitts:


Wiedergabe stellt eine Verbindung zu YouTube her.

Methoden mit einem Parameter

Die Idee ist, dass man sogenannte Methoden verwendet. Als Beispiel stellen wir uns vor, wir wollen für verschiedene Parameter pZahl jeweils die Summe der natürlichen Zahlen von 1 bis zu pZahl ausrechnen und anzeigen lassen. Sagen wir, einmal für pZahl = 10, dann für pZahl = 100 und schließlich für pZahl = 1000. Nun könnte man dies so erledigen:

public class SchlechtesBeispiel {

    public static void main(String[] args) {

        int ergebnis;
        ergebnis = 0;

        for (int zaehler=0; zaehler <= 10; zaehler=zaehler+1){
            ergebnis=ergebnis+zaehler;
        }
        System.out.println("Die Summe der Zahlen von 1 bis 10 lautet "+ergebnis);


        int zweitesErgebnis;
        zweitesErgebnis = 0;

        for (int zaehler=0; zaehler <= 100; zaehler=zaehler+1){
            zweitesErgebnis=zweitesErgebnis+zaehler;
        }
        System.out.println("Die Summe der Zahlen von 1 bis 100 lautet "+zweitesErgebnis);


        int drittesErgebnis;
        drittesErgebnis = 0;

        for (int zaehler=0; zaehler <= 1000; zaehler=zaehler+1){
            drittesErgebnis=drittesErgebnis+zaehler;
        }
        System.out.println("Die Summe der Zahlen von 1 bis 1000 lautet "+drittesErgebnis);

    }

}

Wir sehen schon, wie sich der Programmtext mit leichter Variation mehrmals wiederholt. Diesen Programmtext lagern wir nun in eine Methode aus. Das geschieht so:

public class ErstesBeispiel {

    public static void main(String[] args) {

        summe(10);
        summe(100);
        summe(1000);

    }

    // Untermethode
    private static void summe(int pZahl){
        int ergebnis;
        ergebnis=0;

        for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
            ergebnis=ergebnis+zaehler;
        }

        System.out.println("Die Summe der Zahlen von 1 bis "+pZahl+" lautet "+ergebnis);
    }

}

Neben der main-Methode gibt es nun die weitere Methode summe:

Zwei Männchen. Das linke hat die Aufschrift „main“, das rechte „void summe(int pZahl)“.
Die beiden Methoden können wir uns wie einen Chef mit seinem Mitarbeiter vorstellen.

Die main-Methode kann nun Arbeit an diese Methode abgeben, indem sie ihr eine Zahl – oder genauer eine int-Variable – übergibt. Diese wird von der Methode summe dann unter pZahl gespeichert.

Das Männchen „main“ gibt an das andere einen Zettel mit der Zahl 10.
Der Parameter wird übergeben.

Nun erledigt die Methode summe den ganzen Rest. D.h. sie rechnet zuerst die Summe aus:

Das Männchen „summe“ rechnet.
Die Untermethode erledigt ihre Arbeit.

Dann schreibt sie noch den Antworttext in die Konsole:

„summe“ hält ein Schild mit dem Ergebnis in die Luft.
Die Untermethode präsentiert ihr Ergebnis.

Danach endet der Programmtext der Methode summe. Nun kann die main-Methode ihr wieder eine neue Zahl überreichen und das Ganze beginnt von vorne. Die Methode summe hat jetzt übrigens alles vergessen, was in der vorherigen Berechnung stattgefunden hat, d.h., die beiden Variablen pZahl und ergebnis sind wieder frei für eine neue Berechnung.

Methoden mit mehreren oder gar keinen Parametern

Unsere Methode summe benötigt genau einen Parameter vom Typ int. Wir können aber auch Methoden implementieren, die mehrere Parameter verwenden. Dabei ist auch erlaubt, dass diese Parameter von verschiedenen Typen sind. Sehen wir uns zunächst ein Beispiel für eine Methode mit zwei Parametern vom Typ int an:

public class ZweitesBeispiel {

  public static void main(String[] args) {

    summe(5);

    summe(6,10);
    
    summe(10);

  }

  // Untermethode mit einem Parameter
  private static void summe(int pZahl){
    int ergebnis;
    ergebnis=0;

    for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
      ergebnis=ergebnis+zaehler;
    }

    System.out.println("Die Summe der Zahlen von 1 bis "+pZahl+" lautet "+ergebnis);
  }
  
  // Untermethode mit zwei Parametern
  private static void summe(int pVon, int pBis){
    
    int ergebnis;
    ergebnis=0;

    for (int zaehler=pVon; zaehler <= pBis; zaehler=zaehler+1){
      ergebnis=ergebnis+zaehler;
    }

    System.out.println("Die Summe der Zahlen von "+pVon+" bis "+pBis+" lautet "+ergebnis);
    
  }

}

Wie wir sehen, gibt es hier neben der uns schon bekannten Methode summe(int pZahl) nun auch noch die Methode summe(int pVon, int pBis). Diese kann ebenfalls von der main-Methode aus aufgerufen werden.

Vielleicht wunderst Du Dich, dass wir zwei Methoden mit demselben Namen programmieren dürfen. Generell ist es ja verboten, Zweideutigkeiten entstehen zu lassen. Hier gibt es aber kein Problem denn Java betrachtet nicht nur den Namen der Methode, sondern auch die Anzahl und die Typen der Parameter. Beides zusammen bildet die Signatur der Methode. Geben wir in der main-Methode die Anweisung summe(6, 10); ist es eindeutig, welche der Methoden wir meinen, denn es gibt nur eine einzige mit diesem Namen und zwei Parametern vom Typ int. Wir dürften aber keine weiteren Methoden mit Namen summe und einem oder zwei Parametern von Typ int hinzufügen – auch nicht, wenn die Parameter andere Namen hätten.

Manchmal benötigt man auch Methoden, die ohne Parameter arbeiten. Hier fügen wir nur ein ganz simples Beispiel hinzu:

public class DrittesBeispiel {

  public static void main(String[] args) {

    hallo();
    
    summe(5);

    summe(6,10);
    
    summe(10);

  }

  // Untermethode
  private static void summe(int pZahl){
    int ergebnis;
    ergebnis=0;

    for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
      ergebnis=ergebnis+zaehler;
    }

    System.out.println("Die Summe der Zahlen von 1 bis "+pZahl+" lautet "+ergebnis);
  }
  
  private static void summe(int pVon, int pBis){
    
    int ergebnis;
    ergebnis=0;

    for (int zaehler=pVon; zaehler <= pBis; zaehler=zaehler+1){
      ergebnis=ergebnis+zaehler;
    }

    System.out.println("Die Summe der Zahlen von "+pVon+" bis "+pBis+" lautet "+ergebnis);
    
  }
  
  private static void hallo(){
    System.out.println("Die folgenden Rechnungen wurden durchgeführt:");
  }

}

Die Methode hallo() schreibt nur eine kleine Begrüßung. Das ist nicht sonderlich spannend. Wir sollten uns anhand dieses Beispiels aber merken, dass wir beim Aufruf einer solchen Methode ohne Parameter die leeren Klammern hinzufügen müssen.

Methoden mit Rückgabewert

Auch diesen Abschnitt gibt es als Video:


Wiedergabe stellt eine Verbindung zu YouTube her.

Methoden mit einem Parameter

Wir haben nun Methoden kennengelernt, denen man einen oder auch mehrere Parameter übergibt, die sie dann in irgendeiner Weise verarbeiten, und das Ergebnis auf dem Bildschirm präsentieren. Es könnte aber auch sein, dass wir mit dem Ergebnis gerne weiterarbeiten wollen, weil es womöglich nur ein Zwischenergebnis in einer aufwändigen Rechnung ist. In dieser Situation benötigen wir Methoden mit Rückgabwerten. Eine solche schauen wir uns wieder am Beispiel der Berechnung einer Summe der natürlichen Zahlen von 1 bis zu einem Parameter pZahl an.

Arbeiten wir mit einer solchen Methode, so sieht anfangs alles aus wie bei den Methoden zuvor. D.h.zunächst übergibt die main-Methode an die Methode summe einen Parameter, zum Beispiel wieder die 10:

Das Männchen „main“ gibt an das andere einen Zettel mit der Zahl 10.


Jetzt verarbeitet– wie gewohnt – die Methode summe diese Eingabe:

Das Männchen „summe“ rechnet.

Und nun kommt der Unterschied. Die Methode summe schreibt keine Meldung in die Konsole, sondern sie gibt das Ergebnis ihrer Berechnung an die main-Methode zurück. Dieses Ergebnis ist in diesem Fall also der Rückgabewert:

„summ“ gibt an „main“ das Ergebniss 55 auf einem Zettel.
Die Untermethode gibt ihr Ergebnis an die Hauptmethode.

In der main-Methode können wir mit diesem Ergebnis dann weiter arbeiten. Wir können zum Beispiel weitere Rechnungen anstellen.

Schauen wir uns nun an, wie hier die Methode summe in Java umgesetzt werden kann:

    private static int summe(int pZahl){
        int ergebnis;
        ergebnis=0;

        for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
            ergebnis=ergebnis+zaehler;
        }

        return ergebnis;
    }

Stellen wir dem noch einmal die alte Version ohne Rückgabewert gegenüber:

    private static void summe(int pZahl){
        int ergebnis;
        ergebnis=0;

        for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
            ergebnis=ergebnis+zaehler;
        }

        System.out.println("Die Summe der Zahlen von 1 bis "+pZahl+" lautet "+ergebnis);
    }

Es sollten zwei Unterschiede auffallen:

  • Im sogenannten Methodenkopf wird in der neuen Methode angegeben, dass hier als Ergebnis ein int-Wert geliefert wird. Das sieht man daran, dass dort statt void nun int steht. Das Wort void hingegeben macht klar, dass kein Ergebnis zurückgegeben wird.
  • Die Rückgabe des Ergebnisses erfolgt mittels return. Da in der alten Version kein Ergebnis zurückgegeben wurde, taucht dort auch kein return auf.

Hier ein Beispiel für eine mögliche main-Methode:

public class ReturnBeispiel {

  public static void main(String[] args) {
    int [] meineZahlen;
    meineZahlen = new int[3];

    meineZahlen[0] = summe(10);
    meineZahlen[1] = summe(100);
    meineZahlen[2] = summe(1000);

    for(int zaehler=0; zaehler<meineZahlen.length; zaehler=zaehler+1){
      System.out.println(meineZahlen[zaehler]);
    }
  }
  

  private static int summe(int pZahl){
    int ergebnis;
    ergebnis=0;

    for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
      ergebnis=ergebnis+zaehler;
    }

    return ergebnis;
  }
  
}

Methoden mit mehreren Parametern

Auch bei Methoden mit Rückgabewert können wir mehrere Parameter verwenden. Hier ein Beispiel, bei dem gleich noch eine Besonderheit auftritt:

public class ReturnBeispielZwei {

  public static void main(String[] args) {
    System.out.println(summe(6,10));
  }
  

  private static int summe(int pZahl){
    int ergebnis;
    ergebnis=0;

    for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
      ergebnis=ergebnis+zaehler;
    }

    return ergebnis;
  }
  
  private static int summe(int pVon, int pBis){
    int ergebnis;
    ergebnis = summe(pBis) - summe (pVon-1);
    return ergebnis;
  }
  
}

Die Methode summe(int pVon, int pBis) ruft wiederum die Methode summe(int pZahl) auf. Sie lässt sich zunächst die Summe der Zahlen von 1 bis pBis berechen und zieht davon die Summe der Zahlen von 1 bis pVon-1 ab. Bei den Methoden ohne Rückgabewert hätten wir ein solches Weiterreichen der Ergebnisse nicht umsetzen können.

Noch kompakter könnten wir die neue Methode auch so schreiben:

private static int summe(int pVon, int pBis){
  return summe(pBis) - summe (pVon-1);
}

Kommen wir abschließend noch zu einer Methode, bei der es auch einen Parameter vom Typ boolean gibt:

public class ReturnBeispiel Drei{

  public static void main(String[] args) {
    summe(true, 1, 10); // Ausgabe
    summe(false, 1, 10); // keine Ausgabe
  }
  

  private static int summe(int pZahl){
    int ergebnis;
    ergebnis=0;

    for (int zaehler=0; zaehler <= pZahl; zaehler=zaehler+1){
      ergebnis=ergebnis+zaehler;
    }

    return ergebnis;
  }
  
  private static int summe(int pVon, int pBis){
    return summe(pBis) - summe (pVon-1);
  }
  
  private static int summe(boolean pAusgabe, int pVon, int pBis){
    int ergebnis;
    ergebnis = summe(pVon, pBis);
    
    if(pAusgabe){
      System.out.println(ergebnis);
    }
    
    return ergebnis;
  }
}

Bei der letzten Methode können wir mit diesem Parameter bestimmen, ob es zusätzlich zum Rückgabewert auch noch eine Ausgabe in der Konsole geben soll. Ein Aufruf mit der Angabe false würde natürlich nur dann Sinn ergeben, wenn man den Rückgabewert weiter verwerten würde.

Häufiger Fehler

Verwendest Du if-Abfragen in einer Methode mit Rückgabewert, kann sich schnell ein Fehler einschleichen. Siehst Du, wo hier das Problem ist?

private static int summe(boolean pAusgabe, int pVon, int pBis){
  int ergebnis;
  ergebnis = summe(pVon, pBis);

  if(pAusgabe){
    System.out.println(ergebnis);
  } else{			
    return ergebnis;
  } // Fehler!

}

Man könnte denken, dass hier eben entweder eine Ausgabe über die Konsole oder eine Rückgabe des Ergebnisses stattfindet. Aber genau das ist problematisch. Eine Methode mit Rückgabewert muss immer einen Rückgabewert liefern. Diese Methode würde dies jedoch, falls pAusgabe den Wert true hat, nicht tun.