Kapitel 4. Methoden und Tests
Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com
Bis jetzt haben wir Programme geschrieben, die nur eine Methode haben, die main
heißt. In diesem Kapitel werden wir dir zeigen, wie du Programme mit mehreren Methoden organisieren kannst. Außerdem werfen wir einen Blick auf die Klasse Math
, die Methoden für gängige mathematische Operationen bietet. Schließlich besprechen wir Strategien für die schrittweise Entwicklung und das Testen deines Codes.
Neue Methoden definieren
Einige Methoden führen eine Berechnung durch und geben ein Ergebnis zurück. Zum Beispiel liest nextDouble
Eingaben von der Tastatur und gibt sie als double
zurück. Andere Methoden, wie println
, führen eine Folge von Aktionen aus, ohne ein Ergebnis zurückzugeben. Java verwendet das Schlüsselwort void
um solche Methoden zu definieren:
public
static
void
newLine
()
{
System
.
out
.
println
();
}
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
"First line."
);
newLine
();
System
.
out
.
println
(
"Second line."
);
}
In diesem Beispiel sind die Methoden newLine
und main
beide public
, was bedeutet, dass sie von anderen Klassen aus aufgerufen (oder aufgerufen) werden können. Und sie sind beide void
, was bedeutet, dass sie kein Ergebnis zurückgeben (im Gegensatz zu nextDouble
). Die Ausgabe des Programms ist hier zu sehen:
First line. Second line.
Beachte den zusätzlichen Abstand zwischen den Zeilen. Wenn wir mehr Platz zwischen den Zeilen haben wollen, können wir dieselbe Methode wiederholt aufrufen. Oder wir könnten eine weitere Methode (mit dem Namen threeLine
) schreiben, die drei Leerzeilen anzeigt:
public
class
NewLine
{
public
static
void
newLine
()
{
System
.
out
.
println
();
}
public
static
void
threeLine
()
{
newLine
();
newLine
();
newLine
();
}
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
"First line."
);
threeLine
();
System
.
out
.
println
(
"Second line."
);
}
}
In diesem Beispiel lautet der Name der Klasse NewLine
. Klassennamen beginnen üblicherweise mit einem Großbuchstaben. NewLine
enthält drei Methoden, newLine
, threeLine
und main
. Erinnere dich daran, dass in Java zwischen Groß- und Kleinschreibung unterschieden wird. NewLine
und newLine
sind also nicht dasselbe.
Konventionell beginnen Methodennamen mit einem Kleinbuchstaben und verwenden die Großschreibung "Kamel", was ein netter Name für jammingWordsTogetherLikeThis
ist. Du kannst jeden beliebigen Namen für Methoden verwenden, außer main
oder eines der Java-Schlüsselwörter.
Ablauf der Ausführung
Wenn du dir eine Klassendefinition ansiehst, die mehrere Methoden enthält, ist es verlockend, sie von oben nach unten zu lesen. Aber das ist nicht der Ablauf der Ausführung oder die Reihenfolge, in der das Programm tatsächlich ausgeführt wird. Das Programm NewLine
führt die Methoden in der umgekehrten Reihenfolge aus, in der sie aufgelistet sind.
Programme beginnen immer mit der ersten Anweisung von main
, unabhängig davon, wo sie sich in der Quelldatei befindet. Die Anweisungen werden der Reihe nach ausgeführt, bis du zu einem Methodenaufruf gelangst, den du dir als Umweg vorstellen kannst. Anstatt zur nächsten Anweisung zu gehen, springst du zur ersten Zeile der aufgerufenen Methode, führst dort alle Anweisungen aus und kommst dann zurück und machst genau dort weiter, wo du aufgehört hast.
Das klingt einfach, aber erinnere dich daran, dass eine Methode eine andere aufrufen kann. In der Mitte von main
geht das vorherige Beispiel los, um die Anweisungen in threeLine
auszuführen. In threeLine
führt es newLine
aus. Dann ruft newLine
println
auf, was einen weiteren Umweg bedeutet.
Zum Glück kann Java gut verfolgen, welche Methoden gerade laufen. Wenn also println
fertig ist, macht es dort weiter, wo es in newLine
aufgehört hat; wenn newLine
fertig ist, geht es zurück zu threeLine
; und wenn threeLine
fertig ist, kommt es zurück zu main
.
Anfänger fragen sich oft, warum es die Mühe wert ist, andere Methoden zu schreiben, wenn sie alles in main
erledigen können. Das Beispiel NewLine
zeigt ein paar Gründe dafür:
Wenn du eine neue Methode erstellst, kannst du einen Block von Anweisungen benennen, was den Code leichter lesbar und verständlich macht.
Durch die Einführung neuer Methoden kann das Programm kürzer werden, da sich wiederholender Code entfällt. Um zum Beispiel neun aufeinanderfolgende Zeilenumbrüche anzuzeigen, könntest du
threeLine
dreimal aufrufen.Eine gängige Problemlösungstechnik besteht darin, Probleme in Teilprobleme zu zerlegen. Mit diesen Methoden kannst du dich auf jedes Teilproblem einzeln konzentrieren und es dann zu einer Gesamtlösung zusammensetzen.
Am wichtigsten ist vielleicht, dass du durch die Aufteilung deines Codes in mehrere Methoden die Möglichkeit hast, einzelne Teile deines Programms separat zu testen. Es ist einfacher, ein komplexes Programm zum Laufen zu bringen, wenn du weißt, dass jede Methode richtig funktioniert.
Parameter und Argumente
Einige der Methoden, die wir verwendet haben, benötigen Argumente. Das sind die Werte, die du in Klammern angibst, wenn du die Methode aufrufst.
Die Methode println
benötigt zum Beispiel ein Argument String
. Um eine Nachricht anzuzeigen, musst du die Nachricht angeben: System.out.println("Hello")
. Auch die Methode printf
kann mehrere Argumente annehmen. Die Anweisung System.out.printf("%d in = %f cmn", inch, cm)
hat drei Argumente: den Formatstring, den inch
Wert und den cm
Wert.
Wenn du eine Methode aufrufst, gibst du die Argumente an. Wenn du eine Methode definierst, gibst du die Parameter an. Das sind Variablen, die angeben, welche Argumente erforderlich sind. Die folgende Klasse zeigt ein Beispiel:
public
class
PrintTwice
{
public
static
void
printTwice
(
String
s
)
{
System
.
out
.
println
(
s
);
System
.
out
.
println
(
s
);
}
public
static
void
main
(
String
[]
args
)
{
printTwice
(
"Don't make me say this twice!"
);
}
}
Die Methode printTwice
hat einen Parameter namens s
mit dem Typ String
. Wenn du printTwice
aufrufst, musst du ein Argument mit dem Typ String
angeben.
Bevor die Methode ausgeführt wird, wird das Argument dem Parameter zugewiesen. Im Beispiel printTwice
wird das Argument "Don't make me say this twice!"
dem Parameter s
zugewiesen.
Dieser Vorgang wird als Parameterübergabe bezeichnet, weil der Wert von außerhalb der Methode an das Innere weitergegeben wird. Ein Argument kann jede Art von Ausdruck sein. Wenn du also eine String
Variable hast, kannst du ihren Wert als Argument verwenden:
String
message
=
"Never say never."
;
printTwice
(
message
);
Der Wert, den du als Argument angibst, muss denselben (oder einen kompatiblen) Typ haben wie der Parameter. Wenn du zum Beispiel Folgendes versuchst:
printTwice
(
17
);
// syntax error
Du wirst eine Fehlermeldung wie diese erhalten:
File: Test.java [line: 10] Error: method printTwice in class Test cannot be applied to given types; required: java.lang.String found: int reason: actual argument int cannot be converted to java.lang.String by method invocation conversion
Diese Fehlermeldung besagt, dass ein int
Argument gefunden wurde, aber der erforderliche Parameter sollte ein String
sein. Im Fall von printTwice
wandelt Java die Ganzzahl 17
nicht automatisch in die Zeichenkette "17"
um.
Manchmal kann Java ein Argument automatisch von einem Typ in einen anderen umwandeln. Zum Beispiel erfordert Math.sqrt
einen double
, aber wenn du Math.sqrt(25)
aufrufst, wird der Ganzzahlwert 25
automatisch in den Fließkommawert 25.0
umgewandelt.
Parameter und andere Variablen existieren nur innerhalb ihrer eigenen Methoden. In dem print
Twice
Beispiel gibt es kein s
in der Methode main
. Wenn du versuchst, sie dort zu verwenden, bekommst du einen Compilerfehler.
Auch innerhalb von printTwice
gibt es keine message
. Diese Variable gehört zu main
. Da Variablen nur innerhalb der Methoden existieren, in denen sie definiert sind, werden sie oft als lokale Variablen bezeichnet.
Mehrere Parameter
Hier ist ein Beispiel für eine Methode, die zwei Parameter benötigt:
public
static
void
printTime
(
int
hour
,
int
minute
)
{
System
.
out
.
(
hour
);
System
.
out
.
(
":"
);
System
.
out
.
println
(
minute
);
}
Um diese Methode aufzurufen, müssen wir zwei ganze Zahlen als Argumente angeben:
int
hour
=
11
;
int
minute
=
59
;
printTime
(
hour
,
minute
);
Anfänger machen manchmal den Fehler, die Argumente zu erklären:
int
hour
=
11
;
int
minute
=
59
;
printTime
(
int
hour
,
int
minute
);
// syntax error
Das ist ein Syntaxfehler, denn der Compiler sieht int hour
und int minute
als Variablendeklarationen und nicht als Ausdrücke, die Werte darstellen. Du würdest die Typen der Argumente nicht deklarieren, wenn sie nur ganze Zahlen wären:
printTime
(
int
11
,
int
59
);
// syntax error
Wenn du die Codefragmente zusammenfügst, erhältst du das vollständige Programm:
public
class
PrintTime
{
public
static
void
printTime
(
int
hour
,
int
minute
)
{
System
.
out
.
(
hour
);
System
.
out
.
(
":"
);
System
.
out
.
println
(
minute
);
}
public
static
void
main
(
String
[]
args
)
{
int
hour
=
11
;
int
minute
=
59
;
printTime
(
hour
,
minute
);
}
}
printTime
hat zwei Parameter, die hour
und minute
heißen. Und main
hat zwei Variablen, die ebenfalls hour
und minute
heißen. Obwohl sie die gleichen Namen haben, sind diese Variablen nicht identisch. Die hour
in printTime
und die hour
in main
beziehen sich auf unterschiedliche Speicherplätze und können unterschiedliche Werte haben.
Du könntest printTime
zum Beispiel so aufrufen:
int
hour
=
11
;
int
minute
=
59
;
printTime
(
hour
+
1
,
0
);
Bevor die Methode aufgerufen wird, wertet Java die Argumente aus; in diesem Beispiel sind die Ergebnisse 12
und 0
. Dann ordnet es diese Werte den Parametern zu. In printTime
ist der Wert von hour
12
, nicht 11
, und der Wert von minute
ist 0
, nicht 59
. Wenn printTime
einen seiner Parameter ändert, hat diese Änderung keine Auswirkungen auf die Variablen in main
.
Stapeldiagramme
Eine Möglichkeit, den Überblick über die Variablen zu behalten, ist das Zeichnen eines Stack-Diagramms, eines Speicherdiagramms (siehe "Speicherdiagramme"), das die aktuell ausgeführten Methoden zeigt. Für jede Methode gibt es ein Feld, das als Rahmen bezeichnet wird und die Parameter und lokalen Variablen der Methode enthält. Der Name der Methode erscheint außerhalb des Rahmens; die Variablen und Parameter erscheinen innerhalb.
Wie die Speicherdiagramme zeigen auch die Stapeldiagramme Variablen und Methoden zu einem bestimmten Zeitpunkt. Abbildung 4-1 ist ein Stack-Diagramm zu Beginn der Methode printTime
. Beachte, dass main
ganz oben steht, weil es zuerst ausgeführt wurde.
Stack-Diagramme helfen dir, den Geltungsbereich einer Variablen zu visualisieren, also den Bereich eines Programms, in dem eine Variable verwendet werden kann.
Stack-Diagramme sind ein gutes mentales Modell dafür, wie Variablen und Methoden zur Laufzeit funktionieren. Wenn du lernst, die Ausführung eines Programms auf Papier (oder auf einem Whiteboard) zu verfolgen, ist das eine nützliche Fähigkeit, um mit anderen Programmierern zu kommunizieren.
Lernprogramme können automatisch Stack-Diagramme für dich zeichnen. Mit Java Tutor kannst du zum Beispiel ein ganzes Programm vorwärts und rückwärts durchlaufen und bei jedem Schritt die Stack-Frames und Variablen sehen. Wenn du es noch nicht getan hast, solltest du dir die Java-Beispiele auf dieser Website ansehen.
Mathe-Methoden
Du musst nicht immer neue Methoden schreiben, um deine Arbeit zu erledigen. Zur Erinnerung: Die Java-Bibliothek enthält Tausende von Klassen, die du verwenden kannst. Die Klasse Math
bietet zum Beispiel allgemeine mathematische Operationen:
double
root
=
Math
.
sqrt
(
17.0
);
double
angle
=
1.5
;
double
height
=
Math
.
sin
(
angle
);
Die erste Zeile setzt root
auf die Quadratwurzel aus 17. Die dritte Zeile findet den Sinus von 1,5 (den Wert von angle
). Math
ist im Paket java.lang
enthalten, du musst es also nicht importieren.
Die Werte für die trigonometrischen Funktionen -sin
, cos
und tan
- müssen im Bogenmaß angegeben werden. Um von Grad in Bogenmaß umzurechnen, teilst du durch 180 und multiplizierst mit π. Praktischerweise stellt die Klasse Math
eine Konstante namens PI
bereit, die eine Näherung von π enthält:
double
degrees
=
90
;
double
angle
=
degrees
/
180.0
*
Math
.
PI
;
Beachte, dass PI
in Großbuchstaben geschrieben ist. Java erkennt Pi
, pi
oder pie
nicht. Außerdem ist PI
der Name einer Konstante, nicht einer Methode, und steht daher nicht in Klammern. Das Gleiche gilt für die Konstante Math.E
, die eine Annäherung an die Eulersche Zahl darstellt.
Die Umrechnung von und nach Bogenmaß ist eine gängige Operation, daher bietet die Klasse Math
Methoden, die das für dich erledigen:
double
radians
=
Math
.
toRadians
(
180.0
);
double
degrees
=
Math
.
toDegrees
(
Math
.
PI
);
Eine weitere nützliche Methode ist round
, die einen Fließkommawert auf die nächste Ganzzahl rundet und long
zurückgibt. Das folgende Ergebnis ist 63 (aufgerundet von 62,8319):
long
x
=
Math
.
round
(
Math
.
PI
*
20.0
);
Ein long
ist wie ein int
, aber größer. Genauer gesagt verwendet ein int
32 Bits Speicherplatz; der größte Wert, den es speichern kann, ist das sind etwa 2 Milliarden. Eine long
verwendet 64 Bits, also ist der größte Wert was ungefähr 9 Quintillionen entspricht.
Nimm dir eine Minute Zeit, um die Dokumentation für diese und andere Methoden in der Klasse Math
zu lesen. Der einfachste Weg, die Dokumentation für Java-Klassen zu finden, ist eine Websuche nach "Java" und dem Namen der Klasse.
Zusammensetzung
Du hast wahrscheinlich gelernt, wie man einfache Ausdrücke auswertet wie und . Zuerst wertest du den Ausdruck in den Klammern aus, der das Argument der Funktion ist. Dann kannst du die Funktion selbst auswerten, entweder von Hand oder indem du sie in einen Taschenrechner eingibst.
Dieser Prozess kann wiederholt angewendet werden, um komplexere Ausdrücke wie . Zunächst bewerten wir das Argument der innersten Funktion (), dann werte die Funktion selbst aus (), und so weiter.
Genau wie bei mathematischen Funktionen können Java-Methoden zusammengesetzt werden, um komplexe Probleme zu lösen. Das heißt, du kannst eine Methode als Teil einer anderen verwenden. Tatsächlich kannst du jeden Ausdruck als Argument für eine Methode verwenden, solange der resultierende Wert den richtigen Typ hat:
double
x
=
Math
.
cos
(
angle
+
Math
.
PI
/
2.0
);
Diese Anweisung dividiert Math.PI
durch 2, addiert das Ergebnis zu angle
und berechnet den Kosinus der Summe. Du kannst auch das Ergebnis einer Methode als Argument an eine andere Methode weitergeben:
double
x
=
Math
.
exp
(
Math
.
log
(
10.0
));
In Java verwendet die Methode log
immer die Basis e. Diese Anweisung findet also die logarithmische Basis e von 10 und hebt e dann auf diese Potenz an. Das Ergebnis wird x
zugewiesen.
Einige mathematische Methoden benötigen mehr als ein Argument. Zum Beispiel nimmt Math.pow
zwei Argumente und erhöht das erste mit der Potenz des zweiten. Diese Zeile berechnet210 und weist den Wert 1024.0
der Variablen x
zu:
double
x
=
Math
.
pow
(
2.0
,
10.0
);
Bei der Verwendung von Math
Methoden vergessen Anfänger oft das Wort Math
. Wenn du zum Beispiel einfach x = pow(2.0, 10.0)
schreibst, bekommst du einen Compilerfehler:
File: Test.java [line: 5] Error: cannot find symbol symbol: method pow(double,double) location: class Test
Die Meldung cannot find symbol
ist verwirrend, aber die letzten beiden Zeilen geben einen nützlichen Hinweis. Der Compiler sucht nach einer Methode namens pow
in der Datei Test.java (der Datei für dieses Beispiel). Wenn du keinen Klassennamen angibst, wenn du dich auf eine Methode beziehst, sucht der Compiler standardmäßig in der aktuellen Klasse.
Rückgabewerte
Wenn du eine void
Methode aufrufst, steht der Aufruf normalerweise in einer eigenen Zeile. Zum Beispiel:
printTime
(
hour
+
1
,
0
);
Wenn du hingegen eine Methode aufrufst, die einen Wert zurückgibt, musst du etwas mit dem Rückgabewert machen. Normalerweise weisen wir ihn einer Variablen zu oder verwenden ihn als Teil eines Ausdrucks, wie hier:
double
error
=
Math
.
abs
(
expect
-
actual
);
double
height
=
radius
*
Math
.
sin
(
angle
);
Im Vergleich zu den Methoden von void
unterscheiden sich die Methoden mit Wertrückgabe in zweierlei Hinsicht:
Sie deklarieren den Typ des Rückgabewerts (den Rückgabetyp).
Sie verwenden mindestens eine
return
Anweisung, um einen Rückgabewert zu liefern.
Hier ein Beispiel aus einem Programm namens Circle.java
. Die Methode calculateArea
nimmt einen double
als Parameter und liefert die Fläche eines Kreises mit diesem Radius (d.h. πr2):
public
static
double
calculateArea
(
double
radius
)
{
double
result
=
Math
.
PI
*
radius
*
radius
;
return
result
;
}
Wie üblich, ist diese Methode public
und static
. Aber an der Stelle, an der wir normalerweise void
sehen, sehen wir double
, was bedeutet, dass der Rückgabewert dieser Methode double
ist.
Die letzte Zeile ist eine neue Form der return
Anweisung, die bedeutet: "Komme sofort aus dieser Methode zurück und verwende den folgenden Ausdruck als Rückgabewert." Der Ausdruck, den du angibst, kann beliebig komplex sein, also hätten wir diese Methode auch prägnanter schreiben können:
public
static
double
calculateArea
(
double
radius
)
{
return
Math
.
PI
*
radius
*
radius
;
}
Andererseits erleichtern temporäre Variablen wie result
oft das Debugging, vor allem wenn du mit einem interaktiven Debugger durch den Code schreitest (siehe "Tracing mit einem Debugger").
Abbildung 4-2 veranschaulicht, wie Datenwerte durch das Programm fließen. Wenn die Methode main
calculateArea
aufruft, wird der Wert 5.0
dem Parameter radius
zugewiesen. calculateArea
gibt dann den Wert 78.54
zurück, der der Variablen area
zugewiesen wird.
Der Typ des Ausdrucks in der Anweisung return
muss mit dem Rückgabetyp der Methode selbst übereinstimmen. Wenn du angibst, dass der Rückgabetyp double
ist, versprichst du, dass diese Methode irgendwann einen double
Wert liefert. Wenn du versuchst, return
ohne Ausdruck oder return
mit einem Ausdruck des falschen Typs zu verwenden, gibt der Compiler einen Fehler aus.
Inkrementelle Entwicklung
Viele Leute machen den Fehler, eine Menge Code zu schreiben, bevor sie versuchen, ihn zu kompilieren und auszuführen. Dann verbringen sie viel zu viel Zeit mit der Fehlersuche. Ein besserer Ansatz ist die so genannte inkrementelle Entwicklung. Die wichtigsten Aspekte sind folgende:
Beginne mit einem funktionierenden Programm und nimm kleine, schrittweise Änderungen vor. Wenn ein Fehler auftritt, weißt du jederzeit, wo du suchen musst.
Verwende Variablen, um Zwischenwerte zu speichern, damit du sie überprüfen kannst, entweder mit Druckanweisungen oder mit einem Debugger.
Wenn das Programm funktioniert, kannst du mehrere Anweisungen zu zusammengesetzten Ausdrücken zusammenfassen (aber nur, wenn das Programm dadurch nicht schwerer zu lesen ist).
Angenommen, du möchtest den Abstand zwischen zwei Punkten ermitteln, die durch die Koordinaten und . Nach der üblichen Definition:
Der erste Schritt ist zu überlegen, wie eine distance
Methode in Java aussehen sollte. Mit anderen Worten: Was sind die Eingaben (Parameter) und was ist die Ausgabe (Rückgabewert)? Bei dieser Methode sind die Parameter die beiden Punkte, und es liegt nahe, sie durch vier double
Werte darzustellen. Der Rückgabewert ist der Abstand, der auch den Typ double
haben sollte.
Wir können bereits eine Gliederung für die Methode schreiben, die manchmal als Stub bezeichnet wird. Der Stub enthält die Methodendeklaration und eine return
Anweisung:
public
static
double
distance
(
double
x1
,
double
y1
,
double
x2
,
double
y2
)
{
return
0.0
;
// stub
}
Die Anweisung return
ist ein Platzhalter, der nur notwendig ist, damit das Programm kompiliert werden kann. In diesem Stadium tut das Programm noch nichts Nützliches, aber es ist gut, es zu kompilieren, damit wir eventuelle Syntaxfehler finden können, bevor wir weiteren Code hinzufügen.
In der Regel ist es eine gute Idee, über Tests nachzudenken , bevor du neue Methoden entwickelst; so kannst du herausfinden, wie du sie implementieren kannst. Um die Methode zu testen, können wir sie von main
aus aufrufen, indem wir die Beispielwerte verwenden:
double
dist
=
distance
(
1.0
,
2.0
,
4.0
,
6.0
);
Mit diesen Werten ist der horizontale Abstand 3,0 und der vertikale Abstand 4,0. Das Ergebnis sollte also 5,0 sein, die Hypotenuse eines 3-4-5 Dreiecks. Wenn du eine Methode testest, ist es wichtig, die richtige Antwort zu kennen.
Sobald wir den Stub kompiliert haben, können wir beginnen, Code Zeile für Zeile hinzuzufügen. Nach jeder schrittweisen Änderung kompilieren wir das Programm neu und führen es aus. Wenn ein Fehler auftritt, wissen wir genau, wo wir suchen müssen: in den Zeilen, die wir gerade hinzugefügt haben.
Der nächste Schritt besteht darin, die Unterschiede zu finden: und . Wir speichern diese Werte in temporären Variablen namens dx
und dy
, damit wir sie mit Druckanweisungen überprüfen können, bevor wir fortfahren. Sie sollten 3,0 und 4,0 sein:
public
static
double
distance
(
double
x1
,
double
y1
,
double
x2
,
double
y2
)
{
double
dx
=
x2
-
x1
;
double
dy
=
y2
-
y1
;
System
.
out
.
println
(
"dx is "
+
dx
);
System
.
out
.
println
(
"dy is "
+
dy
);
return
0.0
;
// stub
}
Wir werden die Druckanweisungen entfernen, wenn die Methode fertig ist. Code wie dieser wird als Gerüst bezeichnet, weil er für den Aufbau des Programms hilfreich ist, aber nicht Teil des Endprodukts ist.
Der nächste Schritt besteht darin, dx
und dy
zu quadrieren. Wir könnten die Methode Math.pow
verwenden, aber es ist einfacher (und effizienter), jeden Term mit sich selbst zu multiplizieren.
Dann addieren wir die Quadrate und drucken das bisherige Ergebnis aus:
public
static
double
distance
(
double
x1
,
double
y1
,
double
x2
,
double
y2
)
{
double
dx
=
x2
-
x1
;
double
dy
=
y2
-
y1
;
double
dsquared
=
dx
*
dx
+
dy
*
dy
;
System
.
out
.
println
(
"dsquared is "
+
dsquared
);
return
0.0
;
// stub
}
Auch an dieser Stelle solltest du das Programm kompilieren und ausführen und den Zwischenwert überprüfen, der 25,0 sein sollte. Schließlich können wir Math.sqrt
verwenden, um das Ergebnis zu berechnen und zurückzugeben:
public
static
double
distance
(
double
x1
,
double
y1
,
double
x2
,
double
y2
)
{
double
dx
=
x2
-
x1
;
double
dy
=
y2
-
y1
;
double
dsquared
=
dx
*
dx
+
dy
*
dy
;
double
result
=
Math
.
sqrt
(
dsquared
);
return
result
;
}
Wenn du mehr Erfahrung im Programmieren hast, kannst du vielleicht mehr als eine Zeile auf einmal schreiben und debuggen. Wenn du aber viel Zeit mit dem Debuggen verbringst, solltest du kleinere Schritte machen.
Vokabeln
- void
Ein spezieller Rückgabetyp, der angibt, dass die Methode keinen Wert zurückgibt.
- aufrufen.
Die Ausführung einer Methode veranlassen. Auch bekannt als Aufruf einer Methode.
- Ablauf der Ausführung
Die Reihenfolge, in der Java Methoden und Anweisungen ausführt. Sie muss nicht unbedingt von oben nach unten in der Quelldatei sein.
- Argument
Ein Wert, den du übergibst, wenn du eine Methode aufrufst. Dieser Wert muss den Typ haben, den die Methode erwartet.
- Parameter
Eine Information, die eine Methode benötigt, bevor sie ausgeführt werden kann. Parameter sind Variablen: Sie enthalten Werte und haben Typen.
- Parameterübergabe
Der Prozess der Zuweisung eines Argumentwertes an eine Parametervariable.
- lokale Variable
Eine Variable, die innerhalb einer Methode deklariert wird. Auf lokale Variablen kann von außerhalb ihrer Methode nicht zugegriffen werden.
- Stapeldiagramm
Eine grafische Darstellung der Variablen, die zu jeder Methode gehören. Die Methodenaufrufe werden von oben nach unten, im Fluss der Ausführung, gestapelt.
- Rahmen
In einem Stapeldiagramm eine Darstellung der Variablen und Parameter für eine Methode mit ihren aktuellen Werten.
- Umfang
Der Bereich eines Programms, in dem eine Variable verwendet werden kann.
- komponieren
Einfache Ausdrücke und Aussagen zu zusammengesetzten Ausdrücken und Aussagen kombinieren.
- Rückgabetyp
- Rückgabewert
Der Wert, der als Ergebnis eines Methodenaufrufs geliefert wird.
- temporäre Variable
Eine kurzlebige Variable, die oft zur Fehlersuche verwendet wird.
- inkrementelle Entwicklung
Ein Verfahren zur Erstellung von Programmen, bei dem ein paar Zeilen auf einmal geschrieben, kompiliert und getestet werden.
- Stummel
Ein Platzhalter für eine unvollständige Methode, damit die Klasse kompiliert werden kann.
- Gerüst
Code, der während der Programmentwicklung verwendet wird, aber nicht Teil der endgültigen Version ist .
Übungen
Der Code für dieses Kapitel befindet sich im Verzeichnis ch04 von ThinkJavaCode2. Unter "Verwenden der Codebeispiele" findest du Anweisungen zum Herunterladen des Repositorys. Bevor du mit den Übungen beginnst, empfehlen wir dir, die Beispiele zu kompilieren und auszuführen.
Wenn du "Command-Line Testing" noch nicht gelesen hast , wäre jetzt ein guter Zeitpunkt. Darin wird eine effiziente Methode beschrieben, um Programme zu testen, die Eingaben vom Benutzer entgegennehmen und bestimmte Ausgaben anzeigen.
Übung 4-1.
In dieser Übung geht es darum, den Code aus einer früheren Übung in eine Methode umzuwandeln, die Parameter benötigt. Beginne mit einer funktionierenden Lösung zu Übung 2-2.
Schreibe eine Methode namens
printAmerican
, die den Tag, das Datum, den Monat und das Jahr als Parameter annimmt und sie im amerikanischen Format anzeigt.Teste deine Methode, indem du sie von
main
aus aufrufst und die entsprechenden Argumente übergibst. Die Ausgabe sollte in etwa so aussehen (nur das Datum könnte anders sein):Saturday, July 22, 2015
Wenn du
printAmerican
getestet hast, schreibe eine weitere Methode namensprintEuropean
, die das Datum im europäischen Format anzeigt.
Übung 4-2.
In dieser Übung wird der Ablauf eines Programms mit mehreren Methoden überprüft. Lies den folgenden Code und beantworte die Fragen:
public
static
void
main
(
String
[]
args
)
{
zippo
(
"rattle"
,
13
);
}
public
static
void
baffle
(
String
blimp
)
{
System
.
out
.
println
(
blimp
);
zippo
(
"ping"
,
-
5
);
}
public
static
void
zippo
(
String
quince
,
int
flag
)
{
if
(
flag
<
0
)
{
System
.
out
.
println
(
quince
+
" zoop"
);
}
else
{
System
.
out
.
println
(
"ik"
);
baffle
(
quince
);
System
.
out
.
println
(
"boo-wa-ha-ha"
);
}
}
Schreibe die Zahl 1 neben die erste Codezeile in diesem Programm, die ausgeführt werden soll.
Schreibe die Zahl 2 neben die zweite Codezeile, und so weiter bis zum Ende des Programms. Wenn eine Zeile mehr als einmal ausgeführt wird, kann es sein, dass am Ende mehr als eine Zahl neben der Zeile steht.
Wie lautet der Wert des Parameters
blimp
, wennbaffle
aufgerufen wird?Was ist die Ausgabe dieses Programms?
Übung 4-3.
Beantworte die folgenden Fragen, ohne das Programm auf einem Computer auszuführen.
Zeichne ein Stapeldiagramm, das den Zustand des Programms beim ersten Aufruf von
ping
zeigt.Was wird von dem folgenden Programm ausgegeben? Achte genau auf die Platzierung von Leerzeichen und Zeilenumbrüchen.
public
static
void
zoop
()
{
baffle
();
System
.
out
.
(
"You wugga "
);
baffle
();
}
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
(
"No, I "
);
zoop
();
System
.
out
.
(
"I "
);
baffle
();
}
public
static
void
baffle
()
{
System
.
out
.
(
"wug"
);
ping
();
}
public
static
void
ping
()
{
System
.
out
.
println
(
"."
);
}
Übung 4-4.
Wenn du eine Frage dazu hast, ob etwas legal ist und was passiert, wenn es nicht legal ist, ist es eine gute Möglichkeit, das herauszufinden, indem du den Compiler fragst. Beantworte die folgenden Fragen, indem du sie ausprobierst.
Was passiert, wenn du eine Wertmethode aufrufst und nichts mit dem Ergebnis tust, d.h. wenn du es nicht einer Variablen zuweist oder es als Teil eines größeren Ausdrucks verwendest ?
Was passiert, wenn du eine ungültige Methode als Teil eines Ausdrucks verwendest? Probiere zum Beispiel
System.out.println("boo!") + 7;
aus.
Übung 4-5.
Zeichne ein Stack-Diagramm, das den Zustand des Programms beim zweiten Aufruf von zoop
zeigt. Wie lautet die vollständige Ausgabe?
public
static
void
zoop
(
String
fred
,
int
bob
)
{
System
.
out
.
println
(
fred
);
if
(
bob
==
5
)
{
ping
(
"not "
);
}
else
{
System
.
out
.
println
(
"!"
);
}
}
public
static
void
main
(
String
[]
args
)
{
int
bizz
=
5
;
int
buzz
=
2
;
zoop
(
"just for"
,
bizz
);
clink
(
2
*
buzz
);
}
public
static
void
clink
(
int
fork
)
{
System
.
out
.
(
"It's "
);
zoop
(
"breakfast "
,
fork
);
}
public
static
void
ping
(
String
strangStrung
)
{
System
.
out
.
println
(
"any "
+
strangStrung
+
"more "
);
}
Übung 4-6.
Viele Berechnungen lassen sich mit der Multadd-Operation, die drei Operanden benötigt und a * b + c
berechnet, prägnanter ausdrücken. Einige Prozessoren bieten sogar eine Hardware-Implementierung dieser Operation für Fließkommazahlen.
Erstelle ein neues Programm namens
Multadd.java
.Schreibe eine Methode namens
multadd
, die dreidoubles
als Parameter annimmt unda * b + c
zurückgibt.Schreibe eine
main
Methode, diemultadd
testet, indem du sie mit ein paar einfachen Parametern aufrufst, wie1.0, 2.0, 3.0
.Auch in
main
kannst du mitmultadd
die folgenden Werte berechnen:Schreibe eine Methode mit dem Namen
expSum
, die einen Double als Parameter nimmt und mitmultadd
zu berechnen:Tipp: Die Methode zur Erhöhung von e zu einer Potenz lautet
Math.exp
.
Im letzten Teil dieser Übung musst du eine Methode schreiben, die eine andere von dir geschriebene Methode aufruft. Immer wenn du das tust, ist es eine gute Idee, die erste Methode sorgfältig zu testen, bevor du an der zweiten arbeitest. Sonst kann es passieren, dass du zwei Methoden gleichzeitig debuggen musst, was schwierig sein kann.
Eines der Ziele dieser Übung ist es, die Mustererkennung zu trainieren: die Fähigkeit, ein bestimmtes Problem als Beispiel für eine allgemeine Kategorie von Problemen zu erkennen.
Get Think Java, 2. Auflage now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.