Die Semantik einer Wertmethodendeklaration in Java
Die Semantik einer Wertmethodendeklaration beschreibt die Bedeutung einer Wertmethodendeklaration in einem Programm.
Kopf und Proklamation ⃗
Die Bedeutung des Kopfes einer Methodendeklaration kann so verstanden werden, wie dies schon früher für die Proklamation der Dokumentation einer Methode erklärt wurde.
Die Proklamation »static double random()« in der Dokumentation der Methode »java.lang.Math.random()« beschreibt beispielsweise, daß ein Aufrufsausdruck zu jener Methode den Typ »double« hat.
- Dokumentation von »java.lang.Math.random()« (gekürzt und übersetzt)
java.lang
Klasse MathMethodenzusammenfassung
static double random()
- Ergibt einen double-Wert größer oder gleich »0.0« und kleiner als »1.0«.
Entsprechend legt auch der Kopf »public static double random()« in der folgenden Deklaration der Methode »random()« fest, daß ein Aufrufsausdruck zu jener Methode den Typ »double« hat.
- Deklaration einer Wertmethode
public static double random()
{ return java.lang.Math.random(); }
Der Unterschied zwischen einer Proklamation der Dokumentation und einem Kopf einer Deklaration besteht nur darin, daß es sich bei der Proklamation um eine Beschreibung und beim Kopf um eine Festlegung handelt.
Das fehlende »public« in der Methodenzusammenfassung erklärt sich dadurch, daß es dort zur Vereinfachung weggelassen wurde. Es findet sich aber auch in der Dokumentation, und zwar in der detaillierten Dokumentation der Methode »random()«.
Der Rückgabespezifikation einer Methode ⃗
Die Rückgabespezifikation einer Methode legt den Typ des Aufrufs jener Methode fest, lautet sie »void«, so hat der Aufruf keinen Wert.
In der folgenden Methodendeklaration wird beispielsweise festgelegt, daß der Aufrufsausdrucks »f()« den Typ »double« hat.
- Deklaration einer Wertmethode
public static double f()
{ java.lang.System.out.print( "alpha" );
return 7; }
Die Rückgabespezifikation »void« bedeutet, daß die Methode keine Wertmethode ist. Das folgende Programm enthält ein Beispiel für die Deklaration einer void-Methode.
Main.java
public final class Main
{public static void gamma()
{ java.lang.System.out.println( "gamma" ); }public static void main( final java.lang.String[] args )
{ gamma(); }}java.lang.System.out
gamma
»void« ist kein Typ.
Rückgabe der Steuerung ⃗
Durch die Ausführung einer Rückgabeanweisung wird die Ausführung der Methode, deren Deklaration diese Rückgabeanweisung enthält, beendet, wodurch auch die Auswertung des dazugehörigen Aufrufs jener Methode beendet wird.
Man sagt dazu auch, daß die Rückgabeanweisung die „Kontrolle“ („Steuerung“) an den Aufrufer zurückgebe, wodurch sich die Bezeichnung „Rückgabeanweisung“ erklärt. Dies bedeutet, daß die Auswertung des Aufrufs der Methode beendet ist.
In dem folgenden Beispiel wird beispielsweise nur ein »A« ausgegeben, weil die Ausführung der Rückgabeanweisung die Ausführung der Methode »martha« beendet, bevor ein »Z« ausgegeben werden kann.
Main.java
public final class Main
{public static int martha()
{ java.lang.System.out.println( "A" );
return 2;
java.lang.System.out.println( "Z" ); }public static void main( final java.lang.String[] args )
{ martha();
java.lang.System.out.println( "E" ); }}- Protokoll (übersetzt)
Main.java:7: Fehler: unerreichbare Anweisung
java.lang.System.out.println( "Z" ); }
^
1 error
In Java gilt es als Fehler, Anweisungen, wie in dem obigen Programm, in eine Methode zu schreiben, die nie ausgeführt werden können, weil vor ihnen immer eine Rückgabeanweisung ausgeführt wird. Insofern kann man nur sagen, daß das voranstehende Programm ein »A« ausgeben würde, wenn solch ein Programm erlaubt wäre. Das folgende Programm gibt aber beispielsweise tatsächlich ein »A« aus.
Main.java
public final class Main
{public static int nordpol()
{ java.lang.System.out.println( "A" );
return 2; }public static void main( final java.lang.String[] args )
{ nordpol();
java.lang.System.out.println( "E" ); }}Protokoll
A
E
Eine zuvor im Kurs genannte Regel, derzufolge hinter jede Anweisung in einem Block eine weitere Anweisung geschrieben werden kann, wird hier nun dadurch eingeschränkt, daß hinter ein Rückgabeanweisung in einem Block keine weitere Anweisung mehr geschrieben werden kann.
Rückgabe von Werte ⃗
Bei der Ausführung einer Rückgabeanweisung wird der Ausdruck der Rückgabeanweisung ausgewertet. Der Wert des Aufrufs der Methode ist dann der in den Rückgabetyp der Methode gewandelte Wert der bei der Ausführung der Methode ausgeführten Rückgabeanweisung.
In dem folgenden Beispiel erhält der Aufruf »f()« beispielsweise den Wert »7.0«. Die Rückgabeanweisung in der Methode »f()« enthält den Ausdruck »7«, und die Wandlung des Wertes dieses Ausdruck in den Rückgabetyp »double« ergibt den Wert »7.0«. Dadurch legt die Methodendeklaration fest, daß sich bei der Auswertung eines Aufrufsausdrucks zur Methode »f()« der Wert »7.0« ergibt.
Main.java
public final class Main
{public static double f(){ return 7; }
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( f() ); }}java.lang.System.out
7.0
Das folgende Beispiel zeigt, daß der Rückgabeausdruck bei jedem Aufruf der Methode erneut ausgewertet wird.
Main.java
public final class Main
{public static double f(){ return java.lang.Math.random(); }
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( f() );
java.lang.System.out.println( f() ); }}Protokoll
0.7246433810256381
0.4483646187894366
Ausgabe und Rückgabe ⃗
Die beiden folgenden Anweisungen verdeutlichen, was man unter Ausgabe und unter Rückgabe versteht.
- Ausgabe der Zahl 5
java.lang.System.out.print( 5 );
- Rückgabe der Zahl 5
return 5;
Die Verwechslung von „Ausgabe“ und „Rückgabe“ ist ein häufiger Fehler von Anfängern.
Die folgende Methode »ar« gibt den Text »Ausgabe (Wirkung)« aus, und den Text »Wert« zurück. Die Ausgabe ist eine Wirkung des Aufrufs jener Methode, während der Text »Wert« der Wert des Aufrufs ist.
Wertmethoden können also zusätzlich zu ihrem Wert auch noch eine Wirkung haben.
Wird der Aufruf »ar()« in eine Aufrufanweisung geschrieben, so tritt nur die Wirkung der Methode »ar« ein, der Wert des Aufrufs geht verloren.
Main.java
public final class Main
{public static java.lang.String ar()
{ java.lang.System.out.println( "Ausgabe (Wirkung)" );
return "Wert"; }public static void main( final java.lang.String[] args )
{ ar(); }}transcript
Ausgabe (Wirkung)
Wird der Aufruf »ar()« in eine Ausgabeanweisung geschrieben, so tritt die Wirkung der Methode »ar« ein und der Wert des Aufrufs wird ausgegeben.
Main.java
public final class Main
{public static java.lang.String ar()
{ java.lang.System.out.println( "Ausgabe (Wirkung)" );
return "Wert"; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( ar() ); }}transcript
Ausgabe (Wirkung)
Wert
Berechnungsmethoden ⃗
Wenn eine Methode einen Wert berechnen soll, soll sie den Wert zurückgeben (und nicht ausgeben ).
Weiterleitungsmethoden ⃗
Das folgende Programm zeigt die Deklaration einer Weiterleitungsmethode »rand()«, die an »java.lang.Math.random()« weiterleitet.
Main.java
public final class Main
{public static double rand()
{ return java.lang.Math.random(); }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( rand() );
java.lang.System.out.println( rand() ); }}- Protokoll
0.48925279823987223
0.23982983248922463
Erweiterungen von Methoden ⃗
Zu Wertmethoden kann eine Ausgabemethode deklariert werden, die denselben Wert ausgibt (und nicht zurückgibt).
Main.java
public final class Main
{public static java.lang.String wertmethode()
{ return "Wert"; }public static void ausgabemethode()
{ java.lang.System.out.println( wertmethode() ); }public static void main( final java.lang.String[] args )
{ ausgabemethode(); }}Protokoll
Wert
Die Ausgabemethode »ausgabe« erledigt ihre Arbeit, indem sie die Wertmethode »wert« verwendet. Wenn der Wert in der Wertmethode einmal geändert werden sollte, wirkt sich dies gleich auf die auf ihr basierende Ausgabemethode aus. Daher sagen wir auch, daß die Ausgabemethode die Wertmethode erweitere (sie fügt noch etwas zur Berechnung hinzu, nämlich die Ausgabe).
Umgekehrt ist es jedoch nicht möglich, zu einer Ausgabemethode eine entsprechende Wertmethode zu schreiben, die den Wert der Ausgabemethode entnimmt. Daher sind Wertmethoden im allgemeinen flexibler einsetzbar als Ausgabemethoden.
Werte und Wirkungen ⃗
In dem folgenden Programm hat die Methode
- »wertUndWirkung()« sowohl einen Wert als auch eine Wirkung,
- »wirkung()« nur eine Wirkung,
- »wert()« nur einen Wert und
- »nichts()« weder einen Wert noch eine Wirkung.
Main.java
public final class Main
{public static java.lang.String wertUndWirkung()
{ java.lang.System.out.println( "Wirkung" );
return "Wert"; }public static void wirkung()
{ java.lang.System.out.println( "Wirkung" ); }public static java.lang.String wert()
{ return "Wert"; }public static void nichts() { }
public static void main( final java.lang.String[] args )
{ }}
Spionagemethoden ⃗
In Java werden die Operanden binärer Operatoren in der zeitlichen Reihenfolge von links nach rechts ausgewertet.
Eine Spionagemethode ist eine Methode, die geschrieben wird, um dabei zu dienen, den Ablauf eines Programmes zu verstehen.
Spionagemethoden erlauben es uns, zu beobachten, daß die Operanden binärer Operatoren in der zeitlichen Reihenfolge von links nach rechts ausgewertet werden.
Main.java
public final class Main
{public static int zwei()
{ java.lang.System.out.println( "zwei" );
return 2; }public static int vier()
{ java.lang.System.out.println( "vier" );
return 4; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( zwei() * vier() ); }}- Protokoll
zwei
vier
8
Strikte Stellen ⃗
Die zwiefache Ausgabe von »klaus()« durch das folgende Programm illustriert die Striktheit der Stellen der bisher behandelten Operatoren und die Striktheit der Stellen von Aufrufen: Obwohl der Wert von »klaus()« zur Berechnung von »0.0 * klaus()« oder zur Berechnung des Wertes des divideUnsigned-Aufrufs nicht wirklich benötigt wird, wird die Methode »klaus()« in beiden Fällen aufgerufen.
Main.java
public final class Main
{public static int klaus()
{ java.lang.System.out.print( "klaus() " );
return 1; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 0.0 * klaus() );
java.lang.System.out.println( java.lang.Integer.divideUnsigned( 0, klaus() )); }}Protokoll
klaus() 0.0
klaus() 0
Fachsprache
Im folgenden nennen wir in den Aufgaben verwendete Fachverben und dann typischerweise damit verbundene Sprachelemente.
- Tabelle
ausgeben print / println
zurueckgeben, ergeben, berechnen return
Das heißt:
- Wenn eine Funktion etwas ausgeben soll: »print« verwenden.
- Wenn eine Funktion etwas zurückgeben soll: »return« verwenden.
- Wenn eine Funktion etwas ergeben soll: »return« verwenden.
- Wenn eine Funktion etwas berechnen soll: »return« verwenden.
Ü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
{
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 «, dann folgt die Rückgabespezifikation, wie zum Beispiel »void «.
- Danach folgt der Name der Methode, wie zum Beispiel »charly«.
- Danach folgt »()«.
- Nun folgt noch ein Block, welcher bei Methoden, die keine void-Methoden sind, mit einer Rückgabeanweisung enden muß.
Statt dessen kann auch eine Beispielmethode oder ein Beispielprogramm aus der Lektion kopiert und überarbeitet werden.
/ Methodendeklaration
Schreiben Sie eine Deklaration einer Methode mit der Signatur »a()«, die das Zeichen »7« ausgibt.
Die Methode soll außer dem im ersten Absatz Beschriebenen nichts anderes machen und nichts Überflüssiges enthalten.
/ Methodendeklaration (1)
Hinweis für den Dozenten ► Diese Übungsaufgabe sollte erst nach der Nachbesprechung der vorherigen Übungsaufgabe behandelt werden.
Schreiben Sie eine Deklaration einer Methode mit der Signatur »b()«, die den Wert «5» ergibt (ein Aufruf jener Methode soll den Typ »int« haben).
Die Methode soll außer dem im ersten Absatz Beschriebenen nichts anderes machen und nichts Überflüssiges enthalten.
/ Methodendeklaration (2)
Hinweis für den Dozenten ► Diese Übungsaufgabe sollte erst nach der Nachbesprechung der vorherigen Übungsaufgabe behandelt werden.
Schreiben Sie eine Deklaration einer Methode mit der Signatur »c()«, die das Zeichen »9« ausgibt und den Wert «3» zurückgibt (ein Aufruf jener Methode soll den Typ »int« haben).
Die Methode soll außer dem im ersten Absatz Beschriebenen nichts anderes machen und nichts Überflüssiges enthalten.
/ Methodendeklaration _
Ersetzen Sie die Lücke »…« in dem folgenden Text durch die Deklaration einer Wirkmethode »j()«, welche keine Wertmethode ist und welche die Methode mit der Signatur »k()« aufruft und den von der Methode »k()« erhaltenen Rückgabewert ausgibt.
Programm mit Lücke
public final class Main
{public static double k() { return java.lang.Math.exp( java.lang.Math.random() ); }
…
public static void main( final java.lang.String[] args )
{ j(); }}
/ eine Weiterleitungsmethode (Zeilenendmethode) _
Unter einer Weiterleitungsmethode verstehen wir hier eine Methode, deren Rumpf nur eine Rückgabeanweisung, eine Ausgabeanweisung oder eine Aufrufanweisung enthält, die nur den Aufruf einer einzigen Methode enthält (eventuelle Argumente jener Methode sollen also keine Aufrufe enthalten).
Schreiben Sie die Deklaration einer Wertmethode »lineSeparator«, welche die Methode »java.lang.System.lineSeparator()« aufruft und den erhaltenen Wert zurückgibt.
/ eine Weiterleitungsmethode (Zufallszahlenmethode) _
Schreiben Sie die Deklaration einer Wertmethode »rand«, so daß der Wert einer Auswertung des Aufrufausdrucks »rand()« ein zufälliger double-Wert zwischen 0 und 1 ist. Diese Methode soll keine Wirkung haben.
Zusatzaufgaben →
/ Methodendeklaration →
Deklarieren Sie unter Zuhilfenahme der Methode »java.lang.Math.random()« eine Methode »wurf()«, deren Aufruf mit einer Wahrscheinlichkeit von 50 Prozent den Wert 0.0 und mit einer Wahrscheinlichkeit von 50 Prozent den Wert 1.0 hat.
/ Mehrwertsteuersatz →
Hinweis für den Dozenten ► Diese Übungsaufgabe sollte erst nach der Nachbesprechung der vorherigen Übungsaufgabe behandelt werden.
Ersetzen Sie die Lücke »…« in dem folgenden Text durch die Deklaration einer Methode »mehrwertsteuersatz«, welche einen Mehrwertsteuersatz zurückgeben soll, so daß das folgende Programm die Mehrwertsteuern in einem hypothetischen Land mit 11 % Mehrwertsteuer für einen Warenwert von 20,-- und 40,-- Währungseinheiten ausgibt.
Main.java
public final class Main
{…
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 20.00 * mehrwertsteuersatz() );
java.lang.System.out.println( 40.00 * mehrwertsteuersatz() ); }}Erwartete Ausgabe (naeherungsweise)
2.2
4.4
Hinweis für den Dozenten ► Diese Übungsaufgabe sollte erst nach der Nachbesprechung der vorherigen Übungsaufgabe behandelt werden.
/ Würfelmethode →
Schreiben Sie eine Wertmethode, welche eine Pseudozufallszahl vom Typ »double« zurückgibt, die zwischen «1.0» (einschließlich) und «7.0» (ausschließlich ) liegt. Nach jedem Aufruf der Methode soll also eine Zahl zurückgegeben werden, deren Vorkommastelle zwischen »1« (einschließlich) und »6« (einschließlich) liegt, wobei jedes der Zeichen »1«, »2«, »3«, »4«, »5« und »6« mit gleicher Wahrscheinlichkeit als Vorkommastelle vorkommt.
Zusatzanforderung Schreiben Sie eine Wirkmethode, welche unter Verwendung der zuvor geschriebenen Wertmethode eine Zufallszahl zwischen «1.0» (einschließlich) und «6.0» (einschließlich) ausgibt, so daß immer »0« als Nachkommastelle erscheint.
2. Zusatzanforderung Schreiben Sie die Lösung der ersten Zusatzanforderung so um, daß gar keine Nachkommastellen mehr angezeigt werden und nur eine Ziffer zwischen »1« und »6« erscheint.
Anmerkung Diese Übungsaufgabe gehört zum roten Faden „Würfeln“.
/ Deklarieren eines verfälschten Münzwurfes *
Deklarieren Sie unter Zuhilfenahme der Methode »java.lang.Math.random()« eine Methode »wurf()«, die mit einer Wahrscheinlichkeit von 75 Prozent den Wert «0.0» und mit einer Wahrscheinlichkeit von 25 Prozent den Wert «1.0» ergibt.