Verschachtelte Methodenaufrufe / Aufruf-Hierarchie, BlueJ-Debugger
1. Verschachtelung von Methoden-Aufrufen
In "normalen" Java-Programmen werden ständig Methoden aufgerufen, in diesen wieder Methoden aufgerufen etc.. Eine Verschachtelungstiefe von 10 ist und auch wesentlich mehr ist ganz normal. Während des Abarbeitens einer aufgerufenen Methode wartet die Aufrufer-Methode und nach "Rückkehr" des Ablaufes (nach Ende der aufgerufenen Methode) wird das nächste Statement der Aufrufer-Methode ausgeführt.
Das folgende Beispiel zeigt durch die enthaltenen println(…)
-Statements, in welcher Reihenfolge der Code abgearbeitet wird. Auch das "Einsammeln" der Rückgabewerte gibt Einblick.
Sinnvollerweise sollte es in ein BlueJ-Projekt kopiert und dort ausgeführt werden. Startpunkt ist methode_A
.
Noch besser sichtbar wird dieser Ablauf, wenn (innerhalb von BlueJ) in der ersten Zeile von methode_A
… int a = 0;
ein Breakpoint (Details siehe unten) gesetzt wird.
Dann wird bei Methodenaufruf der Debugger aktiv und man kann mit step bzw. step into (siehe Kommentare im Code) den Ablauf direkt verfolgen.
2. Beispiel – auch zum Durchspielen mit dem BlueJ-Debugger
import java.util.Scanner;
public class AufrufHierarchie {
private static int staticCounter = 0;
private int someValue;
public void methode_A() {
staticCounter++;
someValue = 33;
int a = 0; // idealer Platz, um für Debugging Breakpoint zu setzen
String infoA = "methode_A";
String erg = "";
System.out.println("Start " + infoA);
erg += methode_B(); // hier Step INTO
System.out.println("Mitte " + infoA);
erg += methode_C(infoA); // hier Step INTO
a = a + 1;
System.out.println("Ende " + infoA + " - erg: " + erg + "A-fertig;");
}
public String methode_B() {
int b = 1;
String infoB = "methode_B";
String erg = "";
System.out.println("Start " + infoB);
erg += methode_C(infoB); // hier Step INTO
b++; // b = b + 1; // b += 1;
System.out.println("Ende " + infoB);
return erg + "B-fertig;";
}
public String methode_C(String callerInfo) {
staticCounter++;
someValue = 444;
int c = 2;
c += 7; // c = c + 7;
String infoC = "in finaler methode_C - Aufruf aus " + callerInfo;
System.out.println(infoC);
Scanner scanner = new Scanner(System.in);
System.out.println("Scanner wartet auf Eingabe von beliebigem Text, Abschluss mit [RETURN]");
String userInput = scanner.next();
System.out.println("Benutzer hat eingegeben: '" + userInput + "'");
return "C-fertig;";
}
}
3. Kurzeinstieg BlueJ-Debugger
HINWEIS: Das obige Beispiel eignet sich recht gut für erste Schritte mit dem Debugger!
3.1. Zweck
Ein interaktiver Debugger ist dazu da,
-
meist ausgehend von einem gesetzten Breakpoint
-
die Ausführung und Auswirkung der einzelnen programmiersprachlichen Anweisungen/Statements
-
und die Werte aller gerade verfügbaren Variablen
-
und ihre Änderung durch die gerade ausgeführten Statements
beobachtbar zu machen.
3.2. Mittel
Dazu gibt es folgende grundsätzliche Mittel:
-
Breakpoints: (rotes Stoptavel-Symbol am linken Rand) können nur gesetzt werden, wenn Klasse kompiliert ist. Es muss eine operative Zeile sein, keine ausschließlich deklarative wie z.B.
int anzahl;
Setzen von Breakpoints einfach durch Mausklick in den linken Rand des Editor-Fensters. -
Markierung (grün) der vor Ausführung stehende, aktuellen Code-Zeile während des Programmlaufes
-
Debugger-Fenster zur Anzeige aller Informationen und nötigen Buttons (öffnet bei Erreichen des Breakpoints im Programmlauf automatisch).
3.3. Debugger-Fenster
-
(links oben) Dropdown-Liste der gerade laufenden Threads (parallel laufende Programmteile – für Kurzeinstieg BlueJ-Debugger dzt. irrelevant)
-
(links darunter) Liste des "Stapels" der gerade offenen Methoden (-Hierarchie), die aktuell laufende ganz oben.
Wichtig: auch die gerade wartenden, offenen Methoden weiter unten im Stapel können ausgewählt und ihre aktuellen Werte angezeigt werden! -
(rechts oben) Liste der Klassen-Variablen (nur 1 Specherplatz je Klasse nötig, auch Statische Variable genannt)
-
(rechts Mitte) Liste der Instanzvariablen (für jede Instanz separat)
-
(rechts unten) Liste der lokalen Variablen (inklusive Methoden-Parameter)
-
(ganz unten) 5 Buttons (von links nach rechts):
-
Halt … Anhalten des Programmlaufes – z.B. in Endlosschleife (nur während des Methodenlaufes aktiv!)
-
Step … Schritt bis zum nächsten Statement
-
Step into … Schritt in aufgerufene Methode, wenn vorhanden; sonst wie 'Step'
-
Continue … weiter mit normalen Programmlauf (keine Einzelschritte mehr; bis zum nächsten Breakpoint)
-
Terminate … Programm beenden
-
Hier ein Beispiel von Editor-Fenster mit Breakpoint (rot) und aktuellem Statement (grün), danach das Debug-Fenster – links die 3 offenen Methoden *_A, *_B, *_C sowie rechts die 3 Variablen-Arten:
Der Start des Debuggers erfolgt automatisch beim Start des Programms, sobald ein Breakpoint gesetzt ist.
Das Programm läuft wie gewohnt, bis es den ersten Breakpoint antrifft.
Hier hält es VOR Ausführung der markierten Zeile (Breakpoint word überdeckt mit grün) und es kann
-
mit Step oder Step into (u.U. in aufgerufene Methode hinein) ein Schritt getan
-
mit Continue das Programm fortgesetzt (bis zum nächsten Breakpoint)
-
mit Terminate das Programm beendet
werden. Die Werte der Variablen werden dynamisch angepasst, zeigen also immer den aktuellen Wert.