Methoden und das Aufteilen von Programmen in kleinere Teile
Bisher haben wir verschiedene Anweisungen verwendet: Wertzuweisungen, Berechnungen, bedingte Anweisungen und Schleifen.
Die Ausgabe auf dem Bildschirm wurde mit der Anweisung System.out.println()
durchgeführt, und das Einlesen von Werten mit Integer.valueOf(scanner.nextLine())
. if
wurde in bedingten Anweisungen verwendet, und while
sowie for
in Schleifen. Wir stellen fest, dass sich die Ausgabe- und Leseoperationen etwas von if
, while
und for
unterscheiden, da den Ausgabe- und Leseanweisungen Klammern folgen, die Parameter enthalten können, die an die Anweisung übergeben werden. Diejenigen, die "auf Klammern enden", sind eigentlich keine Anweisungen, sondern Methoden.
Technisch gesehen ist eine Methode ein benannter Satz von Anweisungen. Es ist ein Teil eines Programms, das von einem anderen Ort im Code unter dem Namen, der der Methode gegeben wurde, aufgerufen werden kann. Zum Beispiel ruft System.out.println("Ich bin ein Parameter, der an die Methode übergeben wird!")
eine Methode auf, die die Ausgabe auf dem Bildschirm durchführt. Die interne Implementierung der Methode — also der Satz von Anweisungen, die ausgeführt werden — ist verborgen, und Programmierende müssen sich bei der Verwendung der Methode nicht damit befassen.
Bisher haben wir nur vorgefertigte Java-Methoden verwendet. Als Nächstes lernen wir, unsere eigenen Methoden zu erstellen.
Eigene Methoden
Eine Methode ist ein benannter Satz von Anweisungen, der von einem anderen Ort im Programmcode unter seinem Namen aufgerufen werden kann. Programmiersprachen bieten vorgefertigte Methoden an, aber Programmiererin und Programmierer können auch eigene Methoden schreiben. Es wäre tatsächlich ziemlich ungewöhnlich, wenn ein Programm keine vom Programmierenden geschriebenen Methoden verwenden würde, da Methoden helfen, das Programm zu strukturieren. Ab jetzt wird fast jedes Programm im Kurs eigene erstellte Methoden enthalten.
In der Codevorlage werden Methoden außerhalb der geschweiften Klammern der main
, aber innerhalb der "äußersten" geschweiften Klammern geschrieben. Sie können sich oberhalb oder unterhalb der main
befinden.
import java.util.Scanner;
public class Beispiel {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Programmcode
}
// eigene Methoden hier
}
Schauen wir uns an, wie man eine neue Methode erstellt. Wir erstellen die Methode greet
.
public static void greet() {
System.out.println("Greetings from the method world!");
}
Und dann fügen wir sie an eine passende Stelle für eine Methode ein.
import java.util.Scanner;
public class Beispiel {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Programmcode
}
// eigene Methoden hier
public static void greet() {
System.out.println("Greetings from the method world!");
}
}
Die Definition der Methode besteht aus zwei Teilen. Die erste Zeile der Definition enthält den Namen der Methode, d.h. greet
. Auf der linken Seite des Namens stehen die Schlüsselwörter public static void
. Unter der Zeile, die den Namen der Methode enthält, befindet sich ein Codeblock, der von geschweiften Klammern umgeben ist. Innerhalb dieses Blocks befindet sich der Code der Methode — die Anweisungen, die ausgeführt werden, wenn die Methode aufgerufen wird. Die einzige Funktion, die unsere Methode greet
erfüllt, besteht darin, eine Zeile Text auf dem Bildschirm auszugeben.
Der Aufruf einer eigenen Methode ist einfach: Schreiben Sie den Namen der Methode, gefolgt von einem Paar Klammern und einem Semikolon. Im folgenden Codeausschnitt ruft das Hauptprogramm (main) die Methode greet
insgesamt viermal auf.
import java.util.Scanner;
public class ProgramStructure {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Programmcode
System.out.println("Let's try if we can travel to the method world:");
greet();
System.out.println("Looks like we can, let's try again:");
greet();
greet();
greet();
}
// eigene Methoden
public static void greet() {
System.out.println("Greetings from the method world!");
}
}
Die Ausführung des Programms ergibt folgende Ausgabe:
Let's try if we can travel to the method world: Greetings from the method world! Looks like we can, let's try again: Greetings from the method world! Greetings from the method world! Greetings from the method world!
Die Reihenfolge der Ausführung ist bemerkenswert. Die Ausführung des Programms erfolgt durch die sequentielle Ausführung der Zeilen der main
-Methode von oben nach unten, eine nach der anderen. Wenn die aufgerufene Anweisung ein Methodenaufruf ist, wechselt die Programmausführung in die betreffende Methode. Die Anweisungen der Methode werden nacheinander von oben nach unten ausgeführt. Danach kehrt die Ausführung an die Stelle zurück, an der der Methodenaufruf erfolgte, und fährt mit der nächsten Anweisung im Programm fort.
Genau genommen ist das Hauptprogramm (main
) selbst eine Methode. Wenn das Programm startet, ruft das Betriebssystem (besser: die Java Virtual Machine) main
auf. Die main
-Methode ist der Ausgangspunkt des Programms, da die Ausführung von der ersten Zeile beginnt. Die Programmausführung endet am Ende der main
-Methode.
Von nun an, wenn Methoden eingeführt werden, werden wir nicht ausdrücklich erwähnen, dass sie sich an der richtigen Stelle befinden müssen. Methoden können z. B. nicht innerhalb anderer Methoden definiert werden.
Benennung von Methoden
Die Namen von Methoden beginnen mit einem Wort, das vollständig in Kleinbuchstaben geschrieben ist, und die restlichen Wörter beginnen mit einem Großbuchstaben - diese Schreibweise wird als camelCase bezeichnet. Darüber hinaus wird der Code innerhalb von Methoden um vier Zeichen eingerückt.
Im folgenden Codebeispiel ist die Methode schlecht benannt. Sie beginnt mit einem Großbuchstaben und die Wörter sind durch _
-Zeichen getrennt. Die Klammern nach dem Methodennamen haben einen Abstand dazwischen, und die Einrückung im Codeblock ist falsch.
public static void This_method_says_woof ( ) {
System.out.println("woof");
}
Im Gegensatz dazu ist die Methode unten korrekt benannt: Der Name beginnt mit einem Kleinbuchstaben und die Wörter sind im camelCase-Stil zusammengefügt, was bedeutet, dass jedes Wort nach dem ersten mit einem Großbuchstaben beginnt. Die Klammern sitzen nebeneinander und der Inhalt ist korrekt eingerückt (die Methode hat ihren eigenen Codeblock, daher beträgt die Einrückung des Codes vier Zeichen).
public static void thisMethodSaysWoof() {
System.out.println("woof");
}
Loading...
Methodenparameter
Parameter sind Werte, die einer Methode übergeben werden, die in ihrer Ausführung verwendet werden können. Die Parameter einer Methode werden in der obersten Zeile der Methode innerhalb der Klammern nach ihrem Namen definiert. Die Werte der Parameter, die die Methode verwenden kann, werden von den Werten kopiert, die der Methode bei ihrer Ausführung übergeben werden.
Im folgenden Beispiel wird eine parameterisierte Methode greet
definiert. Sie hat einen Parameter vom Typ int
, der numOfTimes
genannt wird.
public static void greet(int numOfTimes) {
int i = 0;
while (i < numOfTimes) {
System.out.println("Greetings!");
i++;
}
}
Wir werden die Methode greet
mit unterschiedlichen Werten aufrufen. Dem Parameter numOfTimes
wird beim ersten Aufruf der Wert 1
und beim zweiten der Wert 3
zugewiesen.
public static void main(String[] args) {
greet(1);
System.out.println("");
greet(3);
}
Greetings!
Greetings! Greetings! Greetings!
Genau wie beim Aufruf der vordefinierten Methode System.out.println
kann auch ein Ausdruck als Parameter übergeben werden.
public static void main(String[] args) {
greet(1 + 2);
}
Greetings! Greetings! Greetings!
Wenn ein Ausdruck als Parameter für eine Methode verwendet wird, wird der Ausdruck vor dem Methodenaufruf ausgewertet. Oben wird der Ausdruck zu 3
ausgewertet, und der endgültige Methodenaufruf hat die Form greet(3);
.
Mehrere Parameter
Eine Methode kann mit mehreren Parametern definiert werden. Beim Aufruf einer solchen Methode werden die Parameter in der gleichen Reihenfolge übergeben.
public static void sum(int first, int second) {
System.out.println("The sum of numbers " + first + " and " + second + " is " + (first + second));
}
sum(3, 5);
int number1 = 2;
int number2 = 4;
sum(number1, number2);
The sum of numbers 3 and 5 is 8 The sum of numbers 2 and 4 is 6
Parameterwerte werden bei einem Methodenaufruf kopiert
Beim Aufruf einer Methode werden die Werte ihrer Parameter kopiert. In der Praxis bedeutet dies, dass sowohl die main
-Methode als auch die aufzurufende Methode Variablen mit demselben Namen verwenden können. Wenn jedoch der Wert der Variablen innerhalb der Methode geändert wird, hat dies keinen Einfluss auf den Wert der Variablen in der main
-Methode, die denselben Namen hat. Schauen wir uns dieses Verhalten mit dem folgenden Programm an.
public class Beispiel {
public static void main(String[] args) {
int min = 5;
int max = 10;
printNumbers(min, max);
System.out.println();
min = 8;
printNumbers(min, max);
}
public static void printNumbers(int min, int max) {
while (min < max) {
System.out.println(min);
min++;
}
}
}
Die Ausgabe des Programms ist:
5 6 7 8 9
8 9
Unten finden Sie dasselbe Programm schrittweise visualisiert. Das Ändern der Werte der Variablen in der Methode printNumbers
hat keinen Einfluss auf die Werte in der main
-Methode, auch wenn sie denselben Namen haben.
Die Methodenparameter sind also unabhängig von den Variablen (oder Parametern) anderer Methoden, selbst wenn sie denselben Namen haben. Wenn eine Variable während eines Methodenaufrufs an eine Methode übergeben wird, wird der Wert dieser Variablen als Wert der in der Methodendefinition deklarierten Parametervariable kopiert. Variablen in zwei separaten Methoden sind unabhängig voneinander.
Um diesen Punkt weiter zu verdeutlichen, betrachten wir das folgende Beispiel. Wir definieren eine Variable namens number
in der main
-Methode. Diese Variable wird als Parameter an die Methode incrementByThree
übergeben.
// Hauptprogramm
public static void main(String[] args) {
int number = 1;
System.out.println("The value of the variable 'number' in the main program: " + number);
incrementByThree(number);
System.out.println("The value of the variable 'number' in the main program: " + number);
}
// Methode
public static void incrementByThree(int number) {
System.out.println("The value of the method parameter 'number': " + number);
number = number + 3;
System.out.println("The value of the method parameter 'number': " + number);
}
Die Ausführung des Programms ergibt folgende Ausgabe.
The value of the variable 'number' in the main program: 1 The value of the method parameter 'number': 1 The value of the method parameter 'number': 4 The value of the variable 'number' in the main program: 1
Wenn die Variable number
innerhalb der Methode erhöht wird, gibt es kein Problem. Dies spiegelt sich jedoch nicht in der Variablen number
des Hauptprogramms wider. Die im Hauptprogramm lebende Variable number
ist eine andere als die number
-Variable der Methode.
Der Parameter number
wird für die Verwendung durch die Methode kopiert, d.h. es wird eine neue Variable namens number
für die Methode incrementByThree
erstellt, in die der Wert der Variablen number
im Hauptprogramm während des Methodenaufrufs kopiert wird. Die Variable number
innerhalb der Methode incrementByThree
existiert nur für die Dauer der Ausführung der Methode und hat keine Verbindung zu der Variable gleichen Namens im Hauptprogramm.
Loading...
Methoden können Werte zurückgeben
Die Definition einer Methode gibt an, ob diese Methode einen Wert zurückgibt oder nicht. Wenn dies der Fall ist, muss die Methodendefinition den Typ des zurückgegebenen Wertes enthalten. Andernfalls wird in der Definition das Schlüsselwort void
verwendet. Die Methoden, die wir bisher erstellt haben, wurden mit dem Schlüsselwort void
definiert, was bedeutet, dass sie keine Werte zurückgegeben haben.
public static **void** incrementByThree() {
...
}
Das Schlüsselwort void
bedeutet, dass die Methode nichts zurückgibt. Wenn wir möchten, dass die Methode einen Wert zurückgibt, muss das Schlüsselwort durch den Typ der Rückgabevariablen ersetzt werden. Im folgenden Beispiel gibt es eine Methode namens alwaysReturnsTen
, die eine Variable vom Typ int
(in diesem Fall den Wert 10) zurückgibt.
Um tatsächlich einen Wert zurückzugeben, verwenden wir das Kommando return
, gefolgt von dem Wert, der zurückgegeben werden soll (oder dem Namen der Variablen, deren Wert zurückgegeben werden soll).
public static int alwaysReturnsTen() {
return 10;
}
Die oben definierte Methode gibt beim Aufruf einen int
-Wert von 10
zurück. Damit der Rückgabewert verwendet werden kann, muss er in einer Variablen gespeichert werden. Dies geschieht auf die gleiche Weise wie eine normale Wertzuweisung zu einer Variablen, indem ein Gleichheitszeichen verwendet wird.
public static void main(String[] args) {
int number = alwaysReturnsTen();
System.out.println("the method returned the number " + number);
}
Der Rückgabewert der Methode wird in einer int
-Variablen platziert, ebenso wie jeder andere int
-Wert. Der Rückgabewert kann auch in jedem anderen Ausdruck verwendet werden.
double number = 4 * alwaysReturnsTen() + (alwaysReturnsTen() / 2) - 8;
System.out.println("the result of the calculation " + number);
Alle bisher kennengelernten Variablentypen können von einer Methode zurückgegeben werden.
Typ des Rückgabewertes | Beispiel |
---|---|
Methode gibt keinen Wert zurück |
|
Methode gibt eine `int`-Variable zurück |
|
Methode gibt eine `double`-Variable zurück |
|
Wenn die Ausführung innerhalb einer Methode den Befehl return
erreicht, endet die Ausführung dieser Methode und der Wert wird an die aufrufende Methode zurückgegeben.
Die Quellcodezeilen nach dem Befehl return
werden nie ausgeführt. Wenn eine Programmiererin oder ein Programmierer Quellcode nach dem return an eine Stelle hinzufügt, die während der Ausführung der Methode niemals erreicht werden kann, gibt der Kompiler (bzw. die IDE) eine Fehlermeldung aus.
Eine Methode wie die folgende ist fehlerhaft (unreachable statement), und der Compiler wird die Datei nicht übersetzen.
public static int faultyMethod() {
return 10;
System.out.println("I claim to return an integer, but I don't.");
}
Die nächste Methode funktioniert, da es möglich ist, jede Anweisung darin zu erreichen — auch wenn es Quellcode unterhalb des return-Kommandos gibt.
public static int functioningMethod(int parameter) {
if (parameter > 10) {
return 10;
}
System.out.println("The number received as parameter is ten or less.");
return parameter;
}
Wenn eine Methode die Form public static void nameOfMethod()
hat, ist es möglich, mit dem Befehl return
aus ihr zurückzukehren — mit anderen Worten, ihre Ausführung an dieser Stelle zu beenden —, ohne dass ein Wert folgt. Zum Beispiel:
public static void division(int numerator, int denominator) {
if (denominator == 0) {
System.out.println("Can not divide by 0!");
return;
}
System.out.println("" + numerator + " / " + denominator + " = " + (1.0 * numerator / denominator));
}
Variablen innerhalb von Methoden definieren
Das Definieren von Variablen innerhalb von Methoden erfolgt auf die gleiche Weise wie im "Hauptprogramm". Die folgende Methode berechnet den Durchschnitt der Zahlen, die sie als Parameter erhält. Die Variablen sum
und avg
werden zur Unterstützung der Berechnung verwendet.
public static double average(int number1, int number2, int number3) {
int sum = number1 + number2 + number3;
double avg = sum / 3.0;
return avg;
}
Eine Möglichkeit, die Methode aufzurufen, ist wie folgt.
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the first number: ");
int first = Integer.valueOf(scanner.nextLine());
System.out.print("Enter the second number: ");
int second = Integer.valueOf(scanner.nextLine());
System.out.print("Enter the third number: ");
int third = Integer.valueOf(scanner.nextLine());
double averageResult = average(first, second, third);
System.out.print("The average of the numbers: " + averageResult);
}
Variablen, die in einer Methode definiert sind, sind nur innerhalb dieser Methode sichtbar. Im obigen Beispiel bedeutet dies, dass die in der Methode average
definierten Variablen sum
und avg
im Hauptprogramm nicht sichtbar sind. Ein typischer Fehler beim Lernen der Programmierung besteht darin, zu versuchen, eine Methode wie folgt zu verwenden.
public static void main(String[] args) {
int first = 3;
int second = 8;
int third = 4;
average(first, second, third);
// Versuch, eine interne Variable der Methode zu verwenden, FUNKTIONIERT NICHT!
System.out.print("The average of the numbers: " + avg);
}
Im obigen Beispiel wird versucht, die in der Methode average
definierte Variable avg
zu verwenden und ihren Wert auszugeben. Die Variable avg
existiert jedoch nur innerhalb der Methode average
, und sie kann außerhalb davon nicht aufgerufen werden.
Auch folgende Fehler sind weit verbreitet.
public static void main(String[] args) {
int first = 3;
int second = 8;
int third = 4;
// Versuch, nur den Methodennamen zu verwenden, FUNKTIONIERT NICHT!
System.out.print("The average of the numbers: " + average);
}
Oben wird versucht, den Namen der Methode average
zu verwenden, als wäre es eine Variable. Eine Methode muss jedoch aufgerufen werden.
Eine weitere Möglichkeit, die funktioniert, ist, den Methodenaufruf direkt innerhalb der Druckanweisung auszuführen:
public static void main(String[] args) {
int first = 3;
int second = 8;
int third = 4;
// Methode innerhalb der Druckanweisung aufrufen, FUNKTIONIERT!
System.out.print("The average of the numbers: " + average(first, second, third));
}
Hier erfolgt der Methodenaufruf zuerst, der den Wert 5.0 zurückgibt, der dann mit Hilfe der Druckanweisung ausgegeben wird.
Loading...
Berechnung des Rückgabewertes innerhalb einer Methode
Der Rückgabewert muss nicht vollständig vordefiniert sein — er kann auch berechnet werden. Die Rückgabeanweisung, die einen Wert aus der Methode zurückgibt, kann auch einen Ausdruck enthalten, der vor der Rückgabe des Wertes ausgewertet wird.
Im folgenden Beispiel definieren wir eine Methode sum
, die die Werte zweier Variablen addiert und ihre Summe zurückgibt. Die zu addierenden Werte der Variablen werden als Parameter der Methode empfangen.
public static int sum(int first, int second) {
return first + second;
}
Wenn die Ausführung der Methode die Anweisung return first + second;
erreicht, wird der Ausdruck first + second
ausgewertet und dann sein Wert zurückgegeben.
Die Methode wird wie folgt aufgerufen. Im Folgenden wird die Methode verwendet, um die Zahlen 2 und 7 zusammenzuzählen. Der durch den Methodenaufruf resultierende Wert wird in die Variable sumOfNumbers
gesetzt.
int sumOfNumbers = sum(2, 7);
// sumOfNumbers ist jetzt 9
Erweitern wir das vorherige Beispiel, damit die Zahlen von einer Benutzerin oder einem Benutzer eingegeben werden.
public static
void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the first number: ");
int first = Integer.valueOf(scanner.nextLine());
System.out.print("Enter the second number: ");
int second = Integer.valueOf(scanner.nextLine());
System.out.print("The combined sum of the numbers is: " + sum(first, second));
}
public static int sum(int first, int second) {
return first + second;
}
Im obigen Beispiel wird der Rückgabewert der Methode nicht in einer Variablen gespeichert, sondern direkt als Teil der Druckoperation verwendet. Die Ausführung der Druckanweisung erfolgt, indem der Computer zuerst die Zeichenkette "The combined sum of the numbers is: "+ sum(first, second)
auswertet. Der Computer sucht zuerst die Variablen first
und second
und kopiert deren Werte als die Werte der Parameter der Methode sum
. Die Methode addiert dann die Werte der Parameter zusammen, danach gibt sie einen Wert zurück. Dieser Wert ersetzt den Methodenaufruf sum
, wobei die Summe an die Zeichenkette "The combined sum of the numbers is: "
angehängt wird.
Da die an eine Methode übergebenen Werte in ihre Parameter kopiert werden, haben die Namen der Parameter und die Namen der im Aufrufer definierten Variablen in Wirklichkeit nichts miteinander zu tun. Im vorherigen Beispiel waren sowohl die Variablen des Hauptprogramms als auch die Parameter der Methode zufällig gleich benannt (first
und second
). Der folgende Code funktioniert genau so, auch wenn die Variablen anders benannt sind:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the first number: ");
int number1 = Integer.valueOf(scanner.nextLine());
System.out.print("Enter the second number: ");
int number2 = Integer.valueOf(scanner.nextLine());
System.out.print("The total sum of the numbers is: " + sum(number1, number2));
}
public static int sum(int first, int second) {
return first + second;
}
Jetzt wird der Wert der Variablen number1
als Wert des Methodenparameters first
kopiert, und der Wert der Variablen number2
wird als Wert des Parameters second
kopiert.
Loading...
Ausführung von Methodenaufrufen und der Aufrufstack
Wie merkt sich der Computer, wohin er nach der Ausführung einer Methode zurückkehren soll?
Die Umgebung, die Java-Quellcode ausführt, behält den Überblick über die aktuell ausgeführte Methode im Aufrufstack. Der Aufrufstack enthält Frames, von denen jeder Informationen über die internen Variablen einer bestimmten Methode und deren Werte enthält. Wenn eine Methode aufgerufen wird, wird im Aufrufstack ein neuer Frame erstellt, der ihre Variablen enthält. Wenn die Ausführung einer Methode endet, wird der Frame, der sich auf eine Methode bezieht, aus dem Aufrufstack entfernt, was dazu führt, dass die Ausführung bei der vorherigen Methode des Stacks fortgesetzt wird.
Auf der rechten Seite der Visualisierung unten wird die Funktionsweise des Aufrufstacks angezeigt. Wenn eine Methode aufgerufen wird, wird im Stack ein neuer Frame erstellt, der nach dem Verlassen des Methodenaufrufs entfernt wird.
Wenn eine Methode aufgerufen wird, bleibt die Ausführung der aufrufenden Methode stehen, bis die Ausführung der aufgerufenen Methode endet. Dies kann mit Hilfe eines Aufrufstacks visualisiert werden. Der Aufrufstack bezieht sich auf den Stapel, der durch die Methodenaufrufe gebildet wird — die derzeit ausgeführte Methode befindet sich immer oben im Stapel, und wenn diese Methode die Ausführung beendet, wird die Ausführung mit der nächsten Methode im Stapel fortgesetzt. Schauen wir uns das folgende Programm an:
public static void main(String[] args) {
System.out.println("Hello world!");
printNumber();
System.out.println("Bye bye world!");
}
public static void printNumber() {
System.out.println("Number");
}
Die Ausführung beginnt bei der ersten Zeile der main
-Methode, wenn das Programm ausgeführt wird. Der Befehl in dieser Zeile druckt den Text "Hello world!"
. Der Aufrufstack des Programms sieht wie folgt aus:
main
Nachdem der Druckbefehl ausgeführt wurde, wechseln wir zur nächsten Anweisung, die die Methode printNumber
aufruft. Das Aufrufen dieser Methode verschiebt die Programmausführung zum Beginn der Methode printNumber
. Währenddessen wartet die main
-Methode auf das Ende der Ausführung der Methode printNumber
. Während wir uns in der Methode printNumber
befinden, sieht der Aufrufstack wie folgt aus:
printNumber main
Wenn die Methode printNumber
abgeschlossen ist, kehren wir zu der Methode zurück, die sich direkt unter der Methode printNumber
im Aufrufstack befindet — in diesem Fall ist es die Methode main
. printNumber
wird aus dem Aufrufstack entfernt, und die Ausführung wird nach dem Aufruf der Methode printNumber
in der main
-Methode fortgesetzt. Der Zustand des Aufrufstacks ist nun wie folgt:
main
Aufrufstack und Methodenparameter
Schauen wir uns den Aufrufstack in einer Situation an, in der Parameter für die Methode definiert wurden.
public static void main(String[] args) {
int beginning = 1;
int end = 5;
printStars(beginning, end);
}
public static void printStars(int beginning, int end) {
while (beginning < end) {
System.out.print("*");
beginning++; // dasselbe wie beginning = beginning + 1
}
}
Die Ausführung des Programms beginnt bei der ersten Zeile der main
-Methode. Die nächsten beiden Zeilen erstellen die Variablen beginning
und end
und weisen ihnen auch Werte zu. Der Zustand des Programms vor dem Aufrufen der Methode printStars
:
Wenn printStars
aufgerufen wird, wechselt die Methode main
in den Wartemodus. Der Methodenaufruf verursacht, dass neue Variablen beginning
und end
für die Methode printStars
erstellt werden, auf die die als Parameter übergebenen Werte angewendet werden. Diese Werte werden von den Variablen beginning
und end
der Methode main
kopiert. Der Zustand des Programms in der ersten Zeile der Ausführung der Methode printStars
ist unten dargestellt.
Wenn der Befehl beginning++
innerhalb der Schleife ausgeführt wird, ändert sich der Wert der Variablen beginning
, die der gerade ausgeführten Methode gehört.
Wie Sie sehen, bleiben die Werte der Variablen in der Methode main
unverändert. Die Ausführung der Methode printStart
würde noch einige Zeit andauern. Wenn die Ausführung dieser Methode endet, wird die Ausführung innerhalb der main
-Methode fortgesetzt.
Betrachten wir dasselbe Programm, indem wir seine Ausführung Schritt für Schritt visualisieren. Die für die Visualisierung verwendete Anwendung vergrößert den Aufrufstack nach unten — auf der rechten Seite steht die Methode main
immer ganz oben, und die aufgerufenen Methoden werden darunter angeordnet.
Aufrufstack und Rückgabe eines Wertes aus einer Methode
Betrachten wir nun ein Beispiel, bei dem die Methode einen Wert zurückgibt. Die main
-Methode des Programms ruft eine separate start
-Methode auf, in der zwei Variablen erstellt, die sum
-Methode aufgerufen und der von der sum
-Methode zurückgegebene Wert ausgegeben wird.
public static void main(String[] args) {
start();
}
public static void start() {
int first = 5;
int second = 6;
int sum = sum(first, second);
System.out.println("Sum: " + sum);
}
public static int sum(int number1, int number2) {
return number1 + number2;
}
Zu Beginn der Ausführung der start
-Methode sieht der Aufrufstack wie in der folgenden Abbildung aus, da sie von der main
-Methode aufgerufen wurde. Die Methode main
hat in diesem Beispiel keine eigenen Variablen:
Nachdem die Variablen first
und second
in der start
-Methode erstellt wurden (d.h. die ersten beiden Zeilen dieser Methode wurden ausgeführt), sieht die Situation wie folgt aus:
Der Befehl int sum = sum(first, second);
erstellt die Variable sum
in der Methode start
und ruft die Methode sum
auf. Die Methode start
wechselt in den Wartemodus. Da die Parameter number1
und number2
in der Methode sum
definiert sind, werden sie zu Beginn der Ausführung der Methode erstellt, und die Werte der als Parameter übergebenen Variablen werden in sie kopiert.
Die Ausführung der Methode sum
addiert die Werte der Variablen number1
und number2
. Der Befehl return
gibt die Summe der Zahlen an die Methode zurück, die sich direkt unter ihr im Aufrufstack befindet — in diesem Fall die Methode start
. Der zurückgegebene Wert wird als Wert der Variablen sum
festgelegt.
Danach wird der Druckbefehl ausgeführt, und dann kehren wir zur main
-Methode zurück. Sobald die Ausführung das Ende der main
-Methode erreicht, endet die Programmausführung.
Eine Methode ruft eine andere Methode auf
Wie wir bereits festgestellt haben, können aus Methoden heraus andere Methoden aufgerufen werden. Ein weiteres Beispiel für diese Technik ist unten angegeben. Wir erstellen die Methode multiplicationTable
, die die Multiplikationstabelle der angegebenen Zahl ausgibt. Die Multiplikationstabelle druckt die Zeilen mit Hilfe der Methode printMultiplicationTableRow
.
public static void multiplicationTable(int max) {
int number = 1;
while (number <= max) {
printMultiplicationTableRow(number, max);
number++;
}
}
public static void printMultiplicationTableRow(int number, int coefficient) {
int printable = number;
while (printable <= number * coefficient) {
System.out.print(" " + printable);
printable += number;
}
System.out.println("");
}
Die Ausgabe des Methodenaufrufs multiplicationTable(3)
sieht beispielsweise so aus.
Unten sehen Sie eine Visualisierung des Methodenaufrufs multiplicationTable(3)
. Beachten Sie, wie die Informationen über den internen Zustand der aufrufenden Methode im Aufrufstack gespeichert werden.