Methoden überladen, Strings parsen
Lösung geprüft
Die Aufgabe der heutigen Stunde ist das Überladen von Methoden! Bei den Konstruktoren haben wir das schon gemacht, jetzt geht es um ganz normale Methoden. Das Prinzip ist dasselbe: gleicher Name, andere Parameterliste. Nebenbei lernen wir, wie man einen String in eine Zahl verwandelt – das braucht man dauernd.
Ein weiteres Beispiel zum Überladen von Methoden: Als Parameter wird
die Grenze der Summe gesetzt. Der String wird in ein Integer
konvertiert. summe hat den Rückgabetyp int
und einen Parameter Grenze vom Typ int. Die
Summe von 0 bis zur Grenze wird berechnet und mit return
zurückgegeben. Die Methoden werden mit Parametern überladen.
Wichtig: Methoden mit gleichen Namen unterscheiden
sich durch die Anzahl der Parameter und deren Typen, aber nicht nach
dem Rückgabetyp. Die Methode String summe(String s); kann
oben nicht hinzugefügt werden, weil es eine Methode
summe(String s) schon gibt.
Lösungsprozess der Aufgabe
/**
*
* Methoden ueberladen und Strings parsen
*
* @version 1.0 vom 22.05.2023
* @meininfokurs.cmrg.site
*/
public class Main2 {
// 1. Summe von 0 bis grenze
public static int summe(int grenze) {
int summe = 0;
for (int i = 1; i < grenze + 1; i++) {
summe += i;
}
return summe;
}
// 2. Gleicher Name, aber ein String kommt rein.
// Der wird in eine Zahl umgewandelt und an Methode 1 weitergereicht.
public static int summe(String s) {
int grenze = Integer.parseInt(s);
return summe(grenze);
}
// 3. Gleicher Name, zwei Parameter: Summe von anfang bis grenze
public static int summe(int anfang, int grenze) {
int summe = 0;
for (int i = anfang; i < grenze + 1; i++) {
summe += i;
}
return summe;
}
public static void main(String[] args) {
int anfang = Integer.parseInt(args[0]);
int grenze = Integer.parseInt(args[1]);
String Ausgabe = "Die Summe von 0 bis " + grenze + " ist " + summe(grenze) + System.lineSeparator();
Ausgabe += "Die Summe von 0 bis " + grenze + " ist " + summe(args[1]) + System.lineSeparator();
Ausgabe += "Die Summe von " + anfang + " bis " + grenze + " ist " + summe(anfang, grenze);
System.out.println(Ausgabe);
} // end of main
} // end of class Main2
In der Aufgabenstellung wird gefordert, dass wir folgende Sachen umsetzen:
- Eine Methode
summe(int grenze), die von 1 bis zur Grenze aufsummiert - Eine überladene Variante
summe(String s), die den Text erst in eine Zahl umwandelt - Eine überladene Variante
summe(int anfang, int grenze)mit eigenem Startwert - Alle drei aus
mainaufrufen und die Ergebnisse ausgeben
classDiagram
class Main2 {
+summe(int) int
+summe(String) int
+summe(int, int) int
+main(String[]) void
}
Wie Java die richtige Methode findet
Drei Methoden heißen summe. Für Java sind das trotzdem
drei verschiedene, weil es nicht nur auf den Namen guckt, sondern auf
Name + Parameterliste zusammen. Das nennt sich
Signatur:
| Signatur | Aufruf | Was passiert |
|---|---|---|
summe(int) | summe(10) | 1+2+…+10 = 55 |
summe(String) | summe("10") | wandelt um und ruft die erste auf → 55 |
summe(int, int) | summe(5, 10) | 5+6+…+10 = 45 |
Beim Kompilieren schaut der Compiler auf die Typen der Argumente und sucht die passende Methode raus. Das passiert nicht erst zur Laufzeit – es steht schon im fertigen Programm fest, welche gemeint ist.
Warum der Rückgabetyp nicht zählt
Das ist der Merksatz aus der Aufgabe, und man versteht ihn am besten, wenn man überlegt, wie Java entscheiden müsste. Angenommen, es gäbe beide:
public static int summe(String s) { ... }
public static String summe(String s) { ... } // geht NICHT
summe("10"); // und welche jetzt?
Bei summe("10"); als eigenständige Zeile wird der
Rückgabewert gar nicht benutzt. Java hätte keine Möglichkeit zu
entscheiden, welche der beiden gemeint ist. Deshalb ist das schon beim
Kompilieren verboten und nicht erst dann, wenn es mehrdeutig wird. Die
Fehlermeldung lautet method summe(String) is already defined.
Integer.parseInt – aus Text wird Zahl
Über args kommen immer Strings rein, auch
wenn du beim Start eine Zahl eingibst. "10" ist Text, mit
dem man nicht rechnen kann. Umgewandelt wird mit:
int grenze = Integer.parseInt("10"); // 10 als Zahl
double d = Double.parseDouble("3.5"); // dasselbe fuer Kommazahlen
Steht etwas drin, das keine Zahl ist, fliegt eine
NumberFormatException. Bei "10 " mit
Leerzeichen geht es übrigens gut, das schneidet Java ab – bei
"zehn" oder "3,5" mit Komma statt Punkt nicht.
Und pass auf, dass du nicht "10" + 5 schreibst: das ergibt
"105", nicht 15. Sobald links ein String steht, hängt
+ an, statt zu addieren.
Eine Methode ruft die andere auf
public static int summe(String s) {
int grenze = Integer.parseInt(s);
return summe(grenze);
}
Das ist der eleganteste Teil der ganzen Aufgabe. Die String-Variante rechnet nichts selbst – sie wandelt nur um und gibt an die int-Variante weiter. Die eigentliche Rechenschleife steht damit genau einmal im Programm. Findest du später einen Fehler darin, musst du ihn nur an einer Stelle beheben.
Das sieht aus wie Rekursion, ist aber keine: die Methode ruft nicht sich selbst auf, sondern ihre überladene Schwester mit einer anderen Signatur. Die Rekursion kommt später bei Suchen und Sortieren.
System.lineSeparator()
Statt "\n" steht im Code System.lineSeparator().
Beides erzeugt einen Zeilenumbruch. Der Unterschied: Windows benutzt
intern zwei Zeichen für einen Umbruch, Linux und macOS nur eins.
lineSeparator() fragt das Betriebssystem und nimmt das
richtige. Für die Konsolenausgabe ist das egal – sobald du Text in eine
Datei schreibst, nicht mehr.
Und so sieht es aus
Trag unter Start > Parameter… zum Beispiel
5 10 ein:
Die Summe von 0 bis 10 ist 55
Die Summe von 0 bis 10 ist 55
Die Summe von 5 bis 10 ist 45
Die ersten beiden Zeilen sind absichtlich gleich. Einmal wurde
summe(grenze) mit der schon umgewandelten Zahl aufgerufen,
einmal summe(args[1]) direkt mit dem String. Zwei
verschiedene Methoden, dasselbe Ergebnis – genau das ist der Punkt beim
Überladen.
i < grenze + 1 statt
i <= grenze. Das ist dasselbe, nur umständlicher
geschrieben. So steht es in der Vorlage, deshalb habe ich es so
gelassen.