Ergänzungen zu Methodendeklarationen in Java
Größere Java -Programme bestehen in der Regel zum größten Teil aus Methodendeklarationen, die zum größten Teil Methodenaufrufe enthalten.
Daran kann man die große Bedeutung von Methoden für die Java -Programmierung erkennen.
Fehlererkennung
In einigen Fällen kann die Verwendung von Konstanten auch helfen, Fehler zu finden.
Bei einem aktuellen JDK und Verwendung von Compiler-Optionen wie »-Xlint:all« und »-Xdiags:verbose« gibt der Compiler beispielsweise eine Warnung beim Übersetzen des folgenden Quelltextes aus. Aber diese Warnung erscheint nur bei Verwendung von »final«.
Main.java
public final class Main
{public static void f()
{ final int n = 0;
java.lang.System.out.println( 1 / n ); }public static void main( final java.lang.String[] args )
{ }}- Konsole
Main.java:5: warning: [divzero] division by zero
java.lang.System.out.println( 1 / n ); }}
^
1 warning
Groß- und Kleinschreibung _
Der Name einer Methode sollte im allgemeinen nur aus kleinen Buchstaben bestehen, jedoch werden Wörter einer natürlichen Sprache (wie Deutsch oder Englisch), die im Namen nicht am Anfang vorkommen, mit großem Anfangsbuchstaben geschrieben. Beispiele sind »weight« und »extraWeight«.
Vorwärtsaufrufe _
Es ist gestattet, eine Methode aufzurufen, die im Quelltext erst nach der Stelle des Aufrufs deklariert wird.
Main.java
public final class Main
{public static void m() { m1(); }
public static void m1() { java.lang.System.out.println( "m1()" ); }
public static void main( final java.lang.String[] args ){ m(); }}
- Protokoll
m1()
Weiterleitungsmethoden _
Eine Weiterleitungsmethode ist eine Methode, die im wesentlichen nichts anderes macht, als eine andere Methode aufzurufen. Im folgenden Programm erlaubt die Weiterleitungsmethode beispielsweise einen etwas kürzeren Aufruf als die Originalmethode.
Main.java
public final class Main
{public static void dumpStack()
{ java.lang.Thread.dumpStack(); }public static void main( final java.lang.String[] args )
{ dumpStack();
dumpStack(); }}- Protokoll
java.lang.Exception: Stack trace
at java.base/java.lang.Thread.dumpStack(Thread.java:1435)
at Main.dumpStack(Main.java:5)
at Main.main(Main.java:8)
java.lang.Exception: Stack trace
at java.base/java.lang.Thread.dumpStack(Thread.java:1435)
at Main.dumpStack(Main.java:5)
at Main.main(Main.java:9)
Aufrufausdrücke →
Ein Aufrufausdruck gehört zum Quelltextmodell. Aufrufsausdrücke wurden schon früher ausführlich behandelt.
Aufrufvorgänge →
Ein Aufrufvorgang gehört zum Laufzeitmodell.
Bei der Auswertung eines Aufrufausdrucks wird eine Methode mit einer passenden Klasse und Signatur ermittelt. Dann wird die Implementation jener Methode ausgeführt.
Aufrufe von Methodendeklarationen des Programms →
Eine Methoden, deren Deklaration in ein Programm geschrieben wurde, kann genauso aufgerufen werden, wie eine Methode der Standardbibliothek. Die Angabe eines Pakets oder eines Klassennamens ist dabei aber nicht nötig.
Wir nehmen an, daß sich die folgende Methodendeklaration in unserem Programm befindet.
- Eine Methodendeklaration
public static void lastkraftwagenAusgeben()
{ java.lang.System.out.print( "Lastkraftwagen" ); }
In dem folgenden Programmbeispiel wird durch die Methodendeklaration »public static void lkw(){ java.lang.System.out.print( "Lastkraftwagen" ); }« eine Methode deklariert, welche durch den Aufruf »lastkraftwagenAusgeben()« im Hauptprogramm aufgerufen wird.
Wird dann der Aufrufausdruck »lastkraftwagenAusgeben()« ausgewertet, erfolgt ein Aufrufvorgang, bei dem die Implementation der Methode mit der Signatur »lastkraftwagenAusgeben()«, also der Block »{ java.lang.System.out.print( "Lastkraftwagen" ); }«, ausgeführt wird, und es wird »Lastkraftwagen« ausgegeben.
Aufrufe von Methoden im Hauptprogramm wurden schon im vorigen Teil des Kurses behandelt.
Das Programm gibt auf diese Weise dann »Lastkraftwagen« aus.
Main.java
public final class Main
{public static void lastkraftwagenAusgeben()
{ java.lang.System.out.print( "Lastkraftwagen" ); }public static void main( final java.lang.String[] args )
{ lastkraftwagenAusgeben(); java.lang.System.out.println(); }}- Protokoll
Lastkraftwagen
Eine Methodendeklaration legt einen Namen für einen Block fest. Wenn dann ein Aufruf mit diesem Namen ausgewertet wird, wird der Block ausgeführt.
Die Auswertung des Aufrufs »lastkraftwagenAusgeben()« bewirkt in dem obigen Programmbeispiel die Ausführung des Blocks »{ java.lang.System.out.print( "Lastkraftwagen" ); }«.
Noch ausführlicher beschrieben:
- Zur Ausführung des Programms wird der Block der main-Methode ausgeführt. (Die Ausführung jedes Programms besteht grundsätzlich immer in der Ausführung des Blocks hinter »public static void main( final java.lang.String[] args )«. Die Ausführung des Programms besteht also in der Ausführung des Blocks »{ lastkraftwagenAusgeben(); }«. )
- Bei der Ausführung des Blocks »{ lastkraftwagenAusgeben(); }« wird die Anweisung »lastkraftwagenAusgeben();« ausgeführt. (Zur Ausführung eines Blocks werden die in ihm enthaltenen Anweisungen hintereinander ausgeführt. Daher wird nun die Anweisung »lastkraftwagenAusgeben();« ausgeführt. Dies ist eine Aufrufanweisung.)
- Bei der Ausführung der Aufrufanweisung »lastkraftwagenAusgeben();« wird der Aufruf »lastkraftwagenAusgeben()« ausgewertet. (Zur Ausführung einer Aufrufanweisung wird der in ihr enthaltene Aufruf ausgewertet. Daher wird nun der Aufruf »lastkraftwagenAusgeben()« ausgewertet.)
- Die Auswertung des Ausdrucks »lastkraftwagenAusgeben()« führt zur Ausführung des Blocks »{ java.lang.System.out.print( "Lastkraftwagen" ); }«. (Bei der Auswertung eines Aufrufausdrucks wird der Hauptblock [der äußerste Block] der aufgerufenen Methode ausgeführt. Dieses ist der Block »{ java.lang.System.out.print( "Lastkraftwagen" ); }«.)
- Bei der Ausführung des Blocks »{ java.lang.System.out.print( "Lastkraftwagen" ); }« wird die Anweisung »java.lang.System.out.print( "Lastkraftwagen" );« ausgeführt. (Zur Ausführung eines Blocks werden die in ihm enthaltenen Anweisungen hintereinander ausgeführt. Daher wird nun die Anweisung »java.lang.System.out.print( "Lastkraftwagen" );« ausgeführt. Dies ist eine Ausgabeanweisung.)
- Die Ausführung der Ausgabeanweisung »java.lang.System.out.print( "Lastkraftwagen" );« führt zur Ausgabe der Zeile »Lastkraftwagen«.
- Nach dem Ende der Ausführung der Anweisung »lastkraftwagenAusgeben();« wird die nächste Anweisung des Hauptprogramms ausgeführt, nämlich »java.lang.System.out.println();«. Diese gibt nun noch ein Zeilenende aus.
Stil →
Benennung einer Methode →
ℛ Stilregel Eine Methode, deren Sinn hauptsächlich in ihrer Wirkung besteht, sollte ein Verb oder eine Verbalphrase als Namen haben, das (beziehungsweise „die“) die Tätigkeit der Methode beschreibt. Beispielsweise »kehrreimAusgeben«, wenn sie einen Kehrreim ausgibt, und nicht einfach »kehrreim«.
(Diese Stilregel wird in diesem Kurs nicht immer umgesetzt.)
Semantik einer Methode →
Eine Methode soll genau eine Aufgabe erledigen und nicht mehr.
Die Deklaration der Methode »lastkraftwagenAusgeben()« in dem folgenden Programm erlaubt es beispielsweise, den Text »Der Lastkraftwagen wendet.« unter Verwendung der Methode auszugeben.
Main.java
public final class Main
{public static void lastkraftwagenAusgeben()
{ java.lang.System.out.print( "Lastkraftwagen" ); }public static void main( final java.lang.String[] args )
{ java.lang.System.out.print( "Der " );
lastkraftwagenAusgeben();
java.lang.System.out.print( " wendet." );
java.lang.System.out.println(); }}- Protokoll
Der Lastkraftwagen wendet.
Würde in der Methode »println« verwendet, so wäre dies aber nicht mehr möglich, da dann immer schon nach »Lastkraftwagen« die Zeile abgeschlossen wird.
Main.java
public final class Main
{public static void lastkraftwagenUndZeilenendeAusgeben()
{ java.lang.System.out.println( "Lastkraftwagen" ); }public static void main( final java.lang.String[] args )
{ java.lang.System.out.print( "Der " );
lastkraftwagenUndZeilenendeAusgeben();
java.lang.System.out.print( " wendet." );
java.lang.System.out.println(); }}- Protokoll
Der Lastkraftwagen
wendet.
Das Problem besteht darin, daß die Methode »lastkraftwagenUndZeilenendeAusgeben()« das Wort »Lastkraftwagen« und ein Zeilenende ausgibt. Sie macht also zwei Sachen!
Wenn eine Methode zwei Sachen macht, dann ist es aber nicht mehr möglich, die eine Sache ohne die andere zu erhalten. Die Methode kann dann nicht mehr eingesetzt werden, wenn nur eine der beiden Sachen benötigt wird.
Falls eine Methode »lastkraftwagenUndZeilenendeAusgeben()« benötigt wird, die ein Zeilenende ausgibt, dann kann sie als Methode, die zwei andere Methoden kombiniert (und damit auch wieder nur eine Sache tut), definiert werden, so daß die Methode »lastkraftwagenAusgeben()« weiterhin zur Verfügung steht.
Main.java
public final class Main
{public static void lastkraftwagenAusgeben()
{ java.lang.System.out.print( "Lastkraftwagen" ); }public static void zeilenendeAusgeben()
{ java.lang.System.out.println(); }public static void lastkraftwagenUndZeilenendeAusgeben()
{ lastkraftwagenAusgeben(); zeilenendeAusgeben(); }public static void main( final java.lang.String[] args )
{ lastkraftwagenUndZeilenendeAusgeben();
java.lang.System.out.print( "Der " );
lastkraftwagenAusgeben();
java.lang.System.out.print( " wendet." );
java.lang.System.out.println(); }}- Protokoll
Lastkraftwagen
Der Lastkraftwagen wendet.
ℛ Stilregel Eine Methode soll immer nur eine Sache machen.
Übungsfragen
? Was ist die Ausgabe des folgenden Programms?
Main.java
public final class Main
{public static void eins()
{ java.lang.System.out.print( "zwei" ); }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( "drei" ); }}
? Was ist die Ausgabe des folgenden Programms? (1) →
Main.java
public final class Main
{public static void anton()
{ java.lang.System.out.print( "berta" ); }public static void main( final java.lang.String[] args )
{ anton();
java.lang.System.out.println( "gamma" ); }}
? Was ist die Ausgabe des folgenden Programms? (2) →
Main.java
public final class Main
{public static void zeit()
{ java.lang.System.out.print( "Uhr" ); }public static void main( final java.lang.String[] args )
{ }}
? Was ist die Ausgabe des folgenden Programms? (3) →
Das Zeichen »(« heißt „runde Klammer auf“.
Das Zeichen »)« heißt „runde Klammer zu“.
Das Zeichen »[« heißt „eckige Klammer auf“.
Das Zeichen »]« heißt „eckige Klammer zu“.
Main.java
public final class Main
{public static void alpha()
{ java.lang.System.out.print( "[" );
java.lang.System.out.print( "]" ); }public static void main( final java.lang.String[] args )
{ java.lang.System.out.print( "(" );
alpha();
java.lang.System.out.print( ")" );
java.lang.System.out.println(); }}
Übungsaufgaben
Anleitung „Wie schreibt man eine Methodendeklaration in ein Programm hinein?“
Diese Anleitung ist nur für Leser gedacht, denen das Schreiben einer neuen Methodendeklaration noch schwerfällt. Alle anderen können sie ignorieren.
- Anweisungsrahmen
public final class Main
{/* Hier Methodendeklaration einfuegen */
public static void main( final java.lang.String[] args )
{ }}
- Als Basis für ein Programm kann zunächst der obenstehende Anweisungsrahmen kopiert werden.
- Die neue Methodendeklaration wird direkt vor »public static void main( final java.lang.String[] args )« eingefügt.
- Die neue Methodendeklaration beginnt mit »public static void «.
- Danach folgt der Name der Methode.
- Danach folgt »()«.
- Nun folgt noch ein Block.
- Damit ist die neue Methodendeklaration fertig.
Statt dessen kann auch eine Beispielmethode oder ein Beispielprogramm aus der Lektion kopiert und überarbeitet werden. Hier ist ein Beispielprogramm:
Main.java
public final class Main
{public static void lastkraftwagenAusgeben()
{ java.lang.System.out.print( "Lastkraftwagen" ); }public static void main( final java.lang.String[] args )
{ lastkraftwagenAusgeben(); java.lang.System.out.println(); }}transcript
Lastkraftwagen
/ Textausgabe
Fügen Sie eine Deklaration einer Methode mit der Signatur »alpha()« in den folgenden Quelltext ein, so daß durch die Auswertung des im Hauptprogramm befindlichen Aufrufausdrucks »alpha()« die Anweisung »java.lang.System.out.print( "gamma" );« ausgeführt wird.
Main.txt
public final class Main
{/* Die Deklaration der Methode alpha() hier einfügen */
public static void main( final java.lang.String[] args )
{ alpha(); java.lang.System.out.println(); }}
Bei der Bearbeitung dieser Aufgabe sollen die ersten beiden Zeilen und die letzten beiden Zeilen nicht verändert werden!
Das Ergebnis der Bearbeitung sollte dann »gamma↵« ausgeben.
/ Textausgabe (1) ʀ
Hinweis für den Dozenten ► Diese Reserveaufgabe sollte erst nach der Nachbesprechung der vorigen Übungsaufgabe bearbeitet werden und nur, falls die Bearbeitung der vorigen Übungsaufgabe noch Schwierigkeiten bereitete.
Fügen Sie eine Deklaration einer Methode »gamma()« in den folgenden Quelltext ein, so daß durch die Auswertung des im Hauptprogramm befindlichen Aufrufausdrucks »gamma()« die Anweisung »java.lang.System.out.print( 2 );« ausgeführt wird.
Main.txt
public final class Main
{/* Die Deklaration der Methode gamma() hier einfügen */
public static void main( final java.lang.String[] args )
{ gamma(); java.lang.System.out.println(); }}
Bei der Bearbeitung dieser Aufgabe sollen die ersten beiden Zeilen und die letzten beiden Zeilen nicht verändert werden!
/ Programmieren einer NOP-Methode »nop()« ⃗
Eine NOP-Methode (NOP = “no operation ”) ist eine Methode, die nichts macht. Der Aufruf einer NOP-Methode hat also weder Wert noch Wirkung.
Schreiben Sie eine Deklaration einer NOP-Methode mit dem Namen »nop«!
Als Lösung dieser Übungsaufgabe muß nicht unbedingt ein vollständiges Java -Programm geschrieben werden; es reicht auch, nur eine Methodendeklaration zu schreiben.
/ Zufallszahl ausgeben ⃗
Schreiben Sie eine Deklaration einer Methode »zufallszahlAusgeben()«, so daß die Auswertung eines im Hauptprogramm befindlichen Aufrufausdrucks »zufallszahlAusgeben()« dann eine Zufallszahl ausgibt. (Es soll dabei nicht durch das Programm festgelegt werden, daß immer die gleichen Zufallszahl ausgegeben wird.)
/ Stapelbericht (stack trace ) einhüllen ⃗
Schreiben Sie eine Deklaration einer Methode »stapelAusgeben()«, so daß die Auswertung eines im Hauptprogramm befindlichen Aufrufausdrucks »stapelAusgeben()« dann einen Stapelbericht (stack trace ) ausgibt. (Die Methode »java.lang.Thread.dumpStack« gibt einen Stapelbericht aus.)
/ Refaktor ⃗
Setzen Sie die beiden Paare von Anweisungen, die im folgenden Programm enthalten sind, jeweils in geschweifte Klammern und benennen Sie »text1« dann in »text« um. Vergewissern Sie sich, daß das Programm hinterher weiterhin mit derselben Ausgabe läuft.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{final java.lang.String text = "text";
java.lang.System.out.println( text );final java.lang.String text1 = "text";
java.lang.System.out.println( text1 );}}
transcript
text
text
Schreiben Sie nun eine Methode, die eines der beiden Anweisungspaare enthält. und ersetzen Sie jedes Anweisungspaar im Hauptprogramm dann durch einen Aufruf jener Methode.
/ Würfelsimulation *
Schreiben Sie eine Wirkmethode, welche eine Zufallszahl ausgibt, die zwischen 1.0 (einschließlich) und 7.0 (ausschließlich) liegt. Nach jedem Aufruf der Methode soll also eine Zahl ausgegeben werden, deren Vorkommastelle zwischen 1 (einschließlich) und 6 (einschließlich) liegt, wobei jeder der Werte 1, 2, 3, 4, 5 und 6 mit gleicher Wahrscheinlichkeit als Vorkommastelle vorkommt.
Rufen Sie diese Wirkmethode alsdann fünfmal auf, so daß das Programm fünf solcher Zufallszahlen ausgibt.
Anmerkung Diese Übungsaufgabe gehört zum roten Faden „Würfeln“.