Aufrufe mit mehreren Argumenten in Java
Einleitendes Beispiel
Das folgende Programm zeigt die Berechnung der Summe ‹ 10 + 2 › mit einem Operator.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( 10.0 + 2.0 ); }}transcript
12.0
Neben den unären Operatoren (wie Vorzeichen) gibt es ja auch binäre Operatoren, welche zwei Operanden akzeptieren. Genauso gibt es auch binäre Aufrufe, welche zwei Argumente enthalten.
Das folgende Programm zeigt die Berechnung der Summe ‹ 10 + 2 › mit einem Methodenaufruf.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( java.lang.Double.sum( 10.0, 2.0 )); }}transcript
12.0
- Henderson-Diagramm (nach Peter Henderson (Oxford/Southhampton))
.
:'.
10.0 ---: '.
:sum '-- 12.0
2.0 ---: .'
: .'
:'
Wie man sieht, ist es eine mehr oberflächliche Unterscheidung, ob eine Operation (ein Rechenschritt) nun mit einer Methode oder mit einem Operator geschrieben wird.
Auch im Deutschen kennt man ja die beiden gleichwertigen Sprechweise „10 plus 2 “ und „Summe von 10 und 2 “,
In diesem Kapitel werden Methodennamen, wie »java.lang.Double.sum« vorgestellt, ohne daß die als Beispiel gewählten speziellen Methoden dabei im Vordergrund stehen sollen. Es geht vielmehr darum, die allgemeine Möglichkeit von Aufrufen mit mehreren Argumenten vorzustellen. Deswegen werden an dieser Stelle die Anwendungsmöglichkeiten der Methode »java.lang.Double.sum« nicht weiter vertieft. Es geht hier nicht um die speziellen Möglichkeiten der Anwendung des Namens »java.lang.Double.sum«, sondern darum, wie es allgemein möglich ist, in Aufrufen mehrere Argumente zu verwenden. »java.lang.Double.sum« dient dann lediglich als ein Beispiel dafür.
- Java
java.lang.Double.sum( 2.0, 10.0 )
- auf deutsch:
- ● „der Wert der Auswertung eines Aufrufs der Methode »java.lang.Double.sum« mit den Argumentausdrücken »2.0« und »10.0«“
- ● „»java.lang.Double.sum« von »2.0« und »10.0«“
- ● „die Summe von Zwei und Zehn“
Im allgemeinen spricht man »f(x,y)« als „f von x und y“.
Syntax
Das folgende Syntaxdiagramm für Aufrufausdrücke ist nun gegenüber einer frühere Version erweitert, um die Möglichkeit mehrerer durch ein Komma getrennter Argumente darzustellen.
Mehrere Argumente werden als Ausdruckliste in die runden Aufrufklammern geschrieben und durch ein Komma getrennt. Dieses Komma stellt eine lexikalische Einheit dar, wie man auch dem folgenden Syntaxdiagramm entnehmen kann.
- Aufrufausdruck (Syntaxdiagramm)
Ausdruckliste
.---------------------------.
| .----------. v
---'---.--->| Ausdruck |---.---'--->
^ '----------' |
| .-. |
'-------( , )<------'
'-'Aufruf
.-------. .-. .---------------. .-.
--->| Name |--->( ( )--->| Ausdruckliste |--->( ) )--->
'-------' '-' '---------------' '-'- Ausdruckliste (Beispiel)
10, 2
- Aufrufausdruck (Beispiel)
java.lang.Double.sum( 10, 2 )
Eine in den Argumentklammern eines Methodenaufrufs verwendete Ausdruckliste wird auch Argumentliste genannt.
Auswertung
Bei der Auswertung eines Aufrufausdrucks werden zuerst alle Argumentausdrücke ausgewertet. Dabei wird von links nach rechts vorgegangen, das erste Argument wird also vor dem zweiten ausgewertet.
In dem folgenden Programm wird beispielsweise der Teilausdruck »1+2« vor dem Teilausdruck »3+4« ausgewertet.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( java.lang.Double.sum( 1+2, 3+4 )); }}transcript
10.0
Anschließend wird die durch den Methodennamen angegebenen Methode mit den im vorigen Schritt ermittelten Werten der Argumente verbunden. Solch eine Verbindung einer Methode mit konkreten Argumentwerten zur Laufzeit (nicht bloß mit den Argumentausdrücken ) wird auch eine Inkarnation (der Methode) genannt, genauso wird auch die Herstellung dieser Verbindung genannt.
- Eine Inkarnation der Methode »java.lang.Double.sum«
java.lang.Double.sum(3.0,7.0)
Die Inkarnation wird dann ausgewertet, diese Auswertung wird hier auch Methodenoperation genannt, während wir eine Auswertung einer Operatorinkarnation als Operatoroperation bezeichnen.
Bei der Auswertung des Ausdrucks »java.lang.Double.sum( 1+2, 3+4 )« werden die folgenden drei Operationen ausgeführt (zwei Operatoroperationen und eine Methodenoperation).
- Operationen bei der Auswertung von »java.lang.Double.sum( 1+2, 3+4 )«
- 1+2
- 3+4
- java.lang.Double.sum(3.0,7.0)
Dokumentation
Dieser Abschnitt stellt die Dokumentation der Methode »java.lang.Double.sum« als Beispiel der Dokumentation einer Methode mit mehreren Parametern vor. Mehrere Parameterbeschreibungen werden in der Dokumentation in den runden Klammern jeweils durch ein Komma getrennt.
- Dokumentation von »java.lang.Double.sum« (überarbeitet und übersetzt)
- public static double sum( double x, double y )
- Ergibt x + y.
Ein Aufruf der Methode »java.lang.Double.sum« ergibt die Summe des ersten Argumentwertes und des zweiten Argumentwertes (also das erste Argument „plus“ das zweite Argument). Die voranstehende Dokumentation stellt klar, daß zwei Argumente erwartet werden und daß ein Ergebnis geliefert wird.
In der Dokumentation finden sich die Parameter in den runden Klammern hinter dem Methodennamen aufgelistet, diese Liste der Parameter wird auch Parameterliste genannt (es handelt sich eigentlich nicht um eine Liste der Parameter selber, sondern von Beschreibungen der Parameter).
- Parameterliste (Beispiel)
double x, double y
Es sind nicht nur Methoden mit bis zu zwei Parametern möglich, vielmehr können Methoden beliebig viele Parameter haben.
Insgesamt ist ein Parameter also nun gekennzeichnet durch
- die Methode, zu der er gehört,
- seine Position in der Liste aller Parameter,
- einen Namen und
- einen Typ.
Die Prosa der Dokumentation einer Methode beschreibt auch, wie der Wert des Aufrufs einer Methode festgelegt wird. Der Wert des Aufrufs einer Methode hängt oft von den Werten der Argumente ab und manchmal auch von anderen Umständen. Die Dokumentation beschreibt, wie der Wert des Aufrufs der Methode von den Werten der Argumente und von anderen Umständen abhängt.
Im Falle der Methode »java.lang.Double.sum« wird das Geschehen bei der Auswertung eines Aufrufs beispielsweise durch den Text „Ergibt die Summe von a und b“ aus ihrer Dokumentation bekannt gemacht.
Regeln für das Schreiben von Aufrufen
Beim Schreiben des Aufrufs der Methode müssen genau so viele Argumente angegeben werden, wie Parameter in der Dokumentation stehen.
Der Typ jedes Arguments muß ein Untertyp des Typs des Parameters sein, der sich an derselben Stelle befindet.
Die Zuordnung der Argumentwerte zu den Parametern erfolgt über deren gemeinsame Reihenfolge : Das erste Argument wird dem ersten Parameter zugeordnet, das zweite dem zweiten Parameter und so weiter. Bei der Inkarnation der Methode wird dann der Wert jedes Parameters durch den (in den Parametertyp gewandelten) Wert des Argumentausdrucks an derselben Stelle festgelegt. Der Aufruf »java.lang.Double.sum( 2.0, 3 )« legt beispielsweise den Wert »2.0« für den Parameter »a« und den Wert »3.0« für den Parameter »b« fest. Dementsprechend bedeutete dieser Aufruf dann ‹ 2.0 + 3.0 ›.
Fachbegriffe
Eine Methode mit mindestens einem Parameter ist parametrisiert.
Eine Methode ohne Parameter ist parameterlos.
Eine Methode mit genau einem Parameter ist einparametrig, Eine Methode mit genau zwei Parametern ist zweiparametrig und so weiter.
Beispiel
Bei Multiplikationen kann es zu einem „Überlauf“ und einem aus Sicht der Schulmathematik falschen Ergebnis kommen.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( 1000000 * 1000000 ); }}java.lang.System.out
-727379968
Es gibt einige „exakte“ Methoden (für Vorzeichenwechsel, Addition, Subtraktion und Multiplikation), die bei einem Überlauf einen Fehler melden.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( java.lang.Math.multiplyExact( 100, 10 )); }}- Protokoll
1000
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( java.lang.Math.multiplyExact( 1000000, 1000000 )); }}- Protokoll
Exception in thread "main" java.lang.ArithmeticException: integer overflow
at java.base/java.lang.Math.multiplyExact(Math.java:906)
at Main.main(Main.java:4)
Ausdrücke (Zusammenfassung) ⃗
Ein Ausdruck ist
- ein Literal,
- ein Name,
- eine Operatorausdruck oder
- ein Aufruf.
- Begriffshierarchie der Ausdrücke
Ausdruck
|
|
.--------------------------:-------------------------------------.-------------------------------------.
| | | |
Literal Operatorausdruck Aufruf Name
z.B.: 65 oder "abc" z.B.: -65 oder 2 + 3 | z.B.: java.lang.Math.PI
|
.------------------'------------------.
| |
Aufruf Aufruf
ohne Argumentausdruecke mit Argumentausdruecken
z.B.: java.lang.Math.random() z.B.: java.lang.Math.abs( 2 )
Übungsfragen
? Reihenfolge von Operationen ⃗
Eine Methodenoperation (ein Rechenschritt) ist durch eine Methode und Werte für alle ihre Parameter bestimmt.
Bei der Auswertung des weiter unten stehenden Ausdrucks, werden die folgenden vier Operationen (Rechenschritte) ausgeführt.
- A) »java.lang.Double.sum( 2.0, 2.2 )«,
- B) »java.lang.Math.floor( 2.7 )«,
- C) »java.lang.Double.parseDouble( "2.2" )« und
- D) »"2." + "2"«.
Diese vier Operationen werden aber bei der Auswertung des ganzen Ausdrucks nicht unbedingt auch in dieser Reihenfolge „A, B, C, D“ ausgeführt. In welcher Reihenfolge werden sie ausgeführt?
- Ausdruck
java.lang.Double.sum
( java.lang.Math.floor( 2.7 ), java.lang.Double.parseDouble( "2." + "2" ))Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( java.lang.Double.sum
( java.lang.Math.floor( 2.7 ), java.lang.Double.parseDouble( "2." + "2" ))); }}Protokoll
4.2
Regel Operanden und Argumente eines Operators beziehungsweise einer Methode werden von links nach rechts ausgewertet.
? Verträglichkeit von Dokumentation und Aufruf
Ist der folgende Aufruf mit der darüberstehenden Dokumentation verträglich (in dem Sinne, daß er als Ausdruck in einem Programm vorkommen kann, ohne eine Fehlermeldung hervorzurufen)?
- Dokumentation von »java.lang.Math.hypot« (überarbeitet und übersetzt)
- java.lang.Math.hypot
- Proklamation
- public static double hypot( double x, double y )
- Prosa
- Ergibt √(x² + y²).
- Aufruf von »java.lang.Math.hypot«
java.lang.Math.hypot( 0, 0 )
? Verträglichkeit von Parameterlisten und Argumentlisten ⃗
Welche der folgenden Paare von Parameterlisten und Argumentlisten sind verträglich?
(Das heißt: Welche der folgenden Argumentlisten sind beim Aufruf einer Methode möglich, deren Dokumentation die darüberstehende Parameterliste hat?)
Paar 0
- Parameterliste
int a, double x
- Argumentliste
2, 3
Paar 1
- Parameterliste
int a, double x
- Argumentliste
2.0, 3.0
Paar 2
- Parameterliste
int a, double x, int b
- Argumentliste
2, 3
? Verständnis von Fachbegriffen ⃗
Zu einer (hypothetischen) Methode mit zwei Parametern und dem Namen »k« wird erklärt: „Der Wert von »k« ist der Wert des ersten Arguments.“. Welchen Wert hat demnach »k( 3, 2 )«? Welchen Wert hat »k( k( 5, 1 ), k( 4, 9 ))«?
? Dokumentation verstehen
- Dokumentation von »java.lang.Math.pow« (überarbeitet und übersetzt)
- java.lang.Math.pow
- Proklamation
- public static double pow( double a, double n )
- Prosa
- Ergibt aⁿ.
- Aussprachehinweis
- pow paʊ
- Wie viele Parameter hat die Methode »java.lang.Math.pow«?
- Welche Namen haben die Parameter dieser Methode?
- Welche Typen haben die Parameter dieser Methode?
- Welchen Typ hat ein Aufruf dieser Methode?
- Kann sich der Wert eines Aufrufs dieser Methode ändern, wenn die Argumente vertauscht werden? *
»pow(a,n)« kann auch als „a hoch n“ gesprochen werden.
Übungsaufgaben
/ Ausgabe eines Ergebnisses
Schreiben Sie ein Java -Programm, welches das Ergebnis eines Aufrufs der Methode »java.lang.Math.pow« ausgibt.
Reserveaufgabe _
/ Ausgabe eines Ergebnisses
Schreiben Sie ein Java -Programm, welches das Ergebnis eines Aufrufs der Methode »java.lang.Math.max« ausgibt.
/ Ermittlung der Hypotenuse zweier Katheten _
Schreiben Sie ein Java -Programm, in welchem mit der Methode »java.lang.Math.hypot« die Hypotenuse zu den Kathetenlängen 3 und 4 berechnet wird.
Übungsaufgaben
/ Inkarnation eines Syntaxdiagramms ⃗
Schreiben Sie eine Inkarnation der Kategorie »Ausdruck« des folgenden Syntaxdiagramms. mit dem Namen »java.lang.Math.addExact« und den Ausdrücken »java.lang.Character.charCount(22)« und »22« (in dieser Reihenfolge).
- Aufrufausdruck (Syntaxdiagramm)
Ausdruckliste
.---------------------------.
| .----------. v
---'---.--->| Ausdruck |---.---'--->
^ '----------' |
| .-. |
'-------( , )<------'
'-'Ausdruck
.-------. .-. .---------------. .-.
--->| Name |--->( ( )--->| Ausdruckliste |--->( ) )--->
'-------' '-' '---------------' '-'
Die Lösung soll auf einer von Leerzeilen umgebenden Zeile für sich stehen.
Syntax der Parameterliste *
- Parameterliste
Parameterliste
.----------------------------------------------------.
| |
| .-----. .------------. v
----'---.--->| Typ |--->| Bezeichner |---------------.---'--->
^ '-----' '------------' |
| .-. |
'--------------------( , )<------------------'
'-'Typ .---.
-----.---------->( int )----------.--->
| '---' ^
| .------. |
'-------->( double )---------'
| '------' |
| .----------------. |
'--->( java.lang.String )----'
'----------------'
Operationen *
In diesem Kurs verstehen wir unter einer Methodenoperation einen Rechenschritt, bei dem der Wert einer Methodeninkarnation, also einer Methode zusammen mit Werten für alle ihre Parameter, ermittelt wird.
Beispielsweise legt der Ausdruck »java.lang.Double.sum( 2.0, 2.2 )« eine Methodenoperation fest.
Entsprechend war eine Operatoroperation ein Rechenschritt, der den Wert einer Operatorinkarnation ermittelte.
Eine Operation ist eine Methodenoperation oder eine Operatoroperation.
Eine bloße Methode, wie »java.lang.Double.sum(double,double)« legt noch keine Operation fest, weil ihr noch Werte für die Parameter fehlen.
Parameter im Sprachgebrauch *
Das, was in diesem Text hier als „Parameter“ bezeichnet wird, wird manchmal auch „Formalparameter “, „formaler Parameter “ oder „formales Argument “ (“formal argument ”) genannt.
Das, was in diesem Text hier als „Argument “ (oder „Argumentausdruck “ oder „Argumentwert “) bezeichnet wird, wird manchmal auch „Aktualparameter “, „aktueller Parameter “ oder „aktuelles Argument “ genannt. Manche unterscheiden auch gar nicht zwischen „Parameter “ und „Argument “, sondern nennen beides „Parameter “ oder beides „Argument “ („Januswort“).
In der JLS7 werden die Ausdrücke “formal parameter ” (8.4.1) oder “parameter ” für „Parameter “ beziehungsweise “actual value argument ”, “actual arguments ” oder “argument ” für „Argument “ verwendet. Die Unterscheidung zwischen „Parameter“ und „Argument“ wird also schon gemacht, es wird aber manchaml zur Verdeutlichung “formal ” oder “actual ” vorangestellt.
In Fehlermeldungen bezeichnet der JDK-Compiler 2015 Argumente als “actual arguments ” und Parameter als “formal arguments ”.
Wir betrachten zunächst ein Programm ohne Fehlermeldungen.
Main.java
public class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( java.lang.Math.rint( 2 )); }}java.lang.System.out
2.0
Nun führen wir einen Fehler durch Weglassen eines Arguments ein.
Main.java
public class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( java.lang.Math.rint() ); }}Konsole
Main.java:32: error: method rint in class Math cannot be applied to given types;
{ java.lang.System.out.println( java.lang.Math.rint() ); }}
^
required: double
found: no arguments
reason: actual and formal argument lists differ in length
1 error
Das folgende Programm zeigt die Verwendung von “actual argument ” durch den Compiler.
Main.java
public class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( java.lang.Math.rint( "String" )); }}Konsole
Main.java:32: error: method rint in class Math cannot be applied to given types;
{ java.lang.System.out.println( java.lang.Math.rint( "String" )); }}
^
required: double
found: String
reason: actual argument String cannot be converted to double by method invocation conversion
1 error
Das Adjektiv oder Präfixoid “formal ” („formal“) kennzeichnet immer eine Bezeichnung für einen Parameter. Ein Formalparameter oder Formalargument ist also ein Parameter.
Das Adjektiv oder Präfixoid “actual ” („tatsächlich“/„Aktual-“) kennzeichnet immer eine Bezeichnung für ein Argument. Ein Aktualparameter oder Aktualargument ist also ein Argument.
- Zitate aus der JLS
- “The formal parameters of a method or constructor, if any, are specified by a list of comma-separated parameter specifiers. Each parameter specifier consists of a type (optionally preceded by the final modifier and/or one or more annotations) and an identifier (optionally followed by brackets) that specifies the name of the parameter.”, JLS 8, 8.4.1 Formal Parameters
- “the argument expressions are evaluated ”, JLS 8, 15.12.4 Run-Time Evaluation of Method Invocation
- “The process of evaluating the argument list differs, depending on whether the method being invoked is a fixed arity method or a variable arity method.”, 15.12.4.2 Evaluate Arguments