E3 – Grundlagen der Programmierung
Programmieren als Strukturierung von Verarbeitung und InteraktionDas Themenfeld E3 Grundlagen der Programmierung ist ein zentrales Arbeitsfeld der Einführungsphase. Im Mittelpunkt steht nicht nur das Erlernen einzelner Java-Befehle, sondern der systematische Weg von der Problemstellung zur nachvollziehbaren Lösung.
Die Programmiersprache wird dabei als Mittel zum Zweck genutzt: Sie hilft, Modelle zu präzisieren, Verarbeitungsabläufe zu strukturieren und Ergebnisse zu prüfen. Spätere Themenfelder und Projekte bauen auf diesen Grundlagen auf.
Programmierung wird in E3 als kontrollierte Beschreibung von Abläufen aufgebaut: Anweisungen verändern Zustände, Ausdrücke liefern Werte, Bedingungen steuern Entscheidungen und Wiederholungen. Methoden kapseln solche Verarbeitung so, dass sie benannt, aufgerufen und wiederverwendet werden kann.
Die Kapitel folgen daher einer durchgehenden Lernlinie: Werte und Typen verstehen → Abläufe steuern → Verarbeitung in Methoden kapseln → Datenstrukturen nutzen → EVA/GUI als interaktionsgetriebenes Verarbeitungssystem verstehen → algorithmische Verfahren in Q1.2 vorbereiten.
E3 folgt dabei keinem einzigen Dauerbeispiel, sondern einer wiederkehrenden Denkbewegung: Werte werden gespeichert, Ausdrücke ausgewertet, Bedingungen geprüft, Abläufe gesteuert, Methoden gebildet, Datenstrukturen durchlaufen und Interaktionen über Ereignisse organisiert. Die unterschiedlichen Beispiele zeigen, dass dieselben Programmierideen in verschiedenen Problemstellungen wiederkehren.
Kerncurriculum kompakt
Einordnung und Inhalte des Themenfelds E.3
Einordnung und Inhalte des Themenfelds E.3
A) Allgemeine Einordnung
Programmierung gehört in der Einführungsphase zu den zentralen Primärerfahrungen der Informatik. Lernende entwickeln dabei vor allem Modellierungs- und Problemlösekompetenz, indem sie schrittweise von einer Idee zu einer überprüfbaren Umsetzung gelangen.
Java wird als objektorientierte Sprache genutzt, in E3 steht jedoch zunächst die prozedurale Grundarbeit mit Datentypen, Ausdrücken, Kontrollstrukturen und Methoden im Vordergrund.
B) Inhalte des Themenfelds E.3
- Grundaufbau von Programmen, Syntax und elementare Anweisungen → Kapitel 1
- Variablen, Zuweisungen, primitive Datentypen und Typkonversion → Kapitel 2
- Operatoren, Vergleiche und boolesche Bedingungen → Kapitel 3
- Kontrollstrukturen und Struktogramm-Notation als Grundlage kontrollierter Ablaufmodellierung → Kapitel 4
- EVA-Prinzip als strukturierendes Ordnungsmodell für Eingabe, Verarbeitung und Ausgabe → Kapitel 5
- Methoden, Schnittstellen und wiederverwendbare Verarbeitung → Kapitel 6
- Datenstrukturen mit Arrays und Strings als Arbeitsgrundlage für Verarbeitung → Kapitel 7
- Einstieg in GUI und ereignisgesteuerte Anwendungen als ereignisgesteuertes EVA-System → Kapitel 8
- Von Methoden zu algorithmischen Routinen als Ausblick auf Q1.2 und Q1.3 → Kapitel 9
C) Bedeutung für diese Kursseite
Die Kapitel bilden eine sachlogische Lernfolge: vom Aufbau einfacher Programme über Datentypen und Ausdrücke bis zu Kontrollstrukturen, Methoden, Datenstrukturen, EVA und ersten grafischen Anwendungen.
Die Seite arbeitet deshalb bewusst mit mehreren Beispielkontexten: Rechner, Punktbewertungen, Spielabläufe, Geometrie, Textprüfung, Messwertlisten und GUI-Anwendungen. Der rote Faden liegt nicht im gleichen Gegenstand, sondern in derselben fachlichen Bewegung von Zustand, Auswertung, Entscheidung, Wiederholung, Kapselung, strukturierter Datenarbeit und Interaktion.
Inhalte, Beispiele und Aufgaben sind so angeordnet, dass die fachliche Progression von grundlegenden Programmierschritten bis zu benannten Verarbeitungsroutinen nachvollziehbar bleibt. Konkrete Such- und Sortierverfahren werden erst in Q1.2 systematisch untersucht.
Quelle
Hessisches Ministerium für Kultus, Bildung und Chancen (2024): Kerncurriculum gymnasiale Oberstufe Informatik, Themenfeld E.3. Fachliche Strukturorientierung ergänzt durch das begleitende Java-Skript.
Einführung in Java und Aufbau einfacher Programme
Wie Programme geschrieben, übersetzt und als Folge von Anweisungen aufgebaut werden
Wie Programme geschrieben, übersetzt und als Folge von Anweisungen aufgebaut werden
Die kleinste lauffähige Programmeinheit bildet den Einstieg in die Programmierung. Sie schafft die Grundlage für den späteren Umgang mit Variablen, Datentypen und Berechnungen.
1. Konzeptklärung: Programm, Quelltext und Ausführung
Ein Programm ist eine formal beschriebene Folge ausführbarer Anweisungen zur Lösung eines Problems.
In Java wird diese Beschreibung als Quelltext in .java-Dateien notiert.
Der Quelltext ist menschenlesbar, aber nicht direkt maschinenausführbar.
2. Strukturelle Einordnung: Übersetzung und Laufzeit
Java-Programme durchlaufen zwei klar getrennte Schritte.
Zunächst übersetzt der Compiler den Quelltext in Bytecode (.class), anschließend führt die Java Virtual Machine (JVM) diesen Bytecode aus.
Die Trennung von Übersetzung und Ausführung macht nachvollziehbar, warum Übersetzungsfehler und Laufzeitfehler unterschiedliche Ursachen haben.
.java-Datei, für Menschen lesbar
.class-Datei, Zwischenform
Der Quelltext beschreibt das Programm für Menschen. Der Compiler prüft und übersetzt ihn. Die JVM führt den erzeugten Bytecode aus. Sichtbare Ausgaben oder Laufzeitfehler entstehen erst, wenn das Programm tatsächlich läuft.
3. Formale Umsetzung: Klasse, main-Methode und Anweisung
Eine ausführbare Java-Anwendung besitzt mindestens eine Klasse mit einer main-Methode als Startpunkt.
Die Anweisungen innerhalb von main werden in der notierten Reihenfolge ausgeführt.
Beim Ausführen sucht die JVM die passende main-Methode.
Erst dort beginnt der Programmablauf; Klassenrahmen, Importe oder später notierte Hilfsmethoden werden nicht einfach von oben nach unten ausgeführt.
Im E3-Kontext dient die Klasse zunächst vor allem als notwendiger Java-Rahmen für ein lauffähiges Programm. Der systematische Objekt- und Klassenbegriff wird später in Q1.1 ausgearbeitet.
4. Beispiel: Minimales, vollständiges Java-Programm
public class HalloWelt {
public static void main(String[] args) {
System.out.println("Hallo Welt");
}
}
Ausführungskette anzeigen
| Schritt | Wirkung | Fachliche Ebene |
|---|---|---|
| 1 | Der Quelltext wird als HalloWelt.java gespeichert. | Quelltext |
| 2 | Der Compiler prüft die Syntax. | Übersetzung |
| 3 | Bei korrektem Code entsteht Bytecode in HalloWelt.class. | Zwischenform |
| 4 | Die JVM sucht die main-Methode als Einstiegspunkt. | Ausführung |
| 5 | println erzeugt die sichtbare Ausgabe. | Konsole |
Konsolenausgabe und Fehlerfall anzeigen
Konsolenausgabe
Hallo Welt
Fehlerfall
Fehlt das Semikolon nach System.out.println("Hallo Welt"), kann der Compiler die Anweisung nicht abschließen.
';' expected
Deutung: Das Programm steht nicht schon als fertige Ausführung im Quelltext. Erst nach erfolgreicher Übersetzung kann die JVM die main-Methode starten und die Ausgabe erzeugen.
Das Beispiel enthält genau eine Klasse, genau eine Startmethode und genau eine auszuführende Anweisung. Damit ist die grundlegende Programmstruktur vollständig sichtbar, ohne zusätzliche Sprachelemente vorwegzunehmen.
Werkzeugpfad: Java-Code prüfen und verändern
Im Java-Werkzeug lassen sich einfache E3-Programme lesen, ausführen und gezielt variieren. Nutze ein Beispiel aus Kapitel 1 bis 4 als PRIMM-Auftrag:
- Code lesen und die Ausgabe vermuten.
- Das Programm im Java-Werkzeug ausführen.
- Eine Variable oder Bedingung verändern.
- Das neue Verhalten mit Anweisung, Ausdruck und Programmzustand erklären.
Direkt üben im Java-Werkzeug
Programmrahmen, Scanner, Variablen und Ausgabe lassen sich hier praktisch prüfen.
5. Typische Fehlvorstellungen
Häufig wird angenommen, die Datei werde „Zeile für Zeile“ ohne Struktur ausgeführt.
Tatsächlich startet die Ausführung an der main-Methode, nicht am Anfang der Datei.
Ebenfalls verbreitet ist die Gleichsetzung von Quelltext und lauffähigem Programm. Der Quelltext muss zuerst erfolgreich übersetzt werden; erst der erzeugte Bytecode ist ausführbar.
Für ein tragfähiges Grundverständnis ist die klare Unterscheidung der Ebenen entscheidend:
Konzept (Programm als Anweisungsfolge), formale Syntax (Klasse und main-Signatur)
und technischer Prozess (Compiler/JVM). Auf dieser Basis werden Programmzustände anschließend
über Variablen und Datentypen explizit und berechenbar gemacht.
Syntax beschreibt dabei, wie Java-Code korrekt geschrieben wird; ebenso wichtig ist die Wirkung
einer Anweisung, eines Ausdrucks oder einer Kontrollstruktur bei der Ausführung.
Diese Brücke von Schreibform zu Wirkung bereitet spätere Theorieperspektiven vor, ohne sie in E3 auszubreiten.
Variablen, Zuweisungen und Datentypen
Werte speichern, verändern und passend typisieren
Werte speichern, verändern und passend typisieren
Nach der Programmgrundstruktur rückt der Inhalt einzelner Anweisungen in den Mittelpunkt: Werte speichern, verändern und mit passenden Typen absichern.
1. Konzeptklärung: Variable als benannter Speicherort
Eine Variable bezeichnet einen Speicherbereich, dem ein Name zugeordnet ist. Der Name ermöglicht den Zugriff auf den aktuell gespeicherten Wert im Programmablauf.
2. Strukturelle Einordnung: Zustand im Programm
Variablen machen Programmzustände explizit. Während ein Programm ausgeführt wird, werden Werte gelesen, berechnet und erneut gespeichert. Dadurch lassen sich Zwischenergebnisse nachvollziehbar darstellen und weiterverarbeiten.
3. Formale Umsetzung: Deklaration, Initialisierung und Zuweisung
Die Deklaration legt Datentyp und Namen fest. Eine Initialisierung weist beim Anlegen bereits einen Startwert zu. Eine spätere Zuweisung ersetzt den bisherigen Wert der Variablen.
public class VariablenDemo {
public static void main(String[] args) {
int kontoStand = 100; // Deklaration + Initialisierung
kontoStand = kontoStand + 25; // Zuweisung: Zustand ändert sich
double temperatur = 21.5;
boolean istVoll = false;
char note = 'A';
System.out.println(kontoStand);
}
}
Bei einer Zuweisung wird zuerst die rechte Seite ausgewertet. Erst danach wird das Ergebnis links gespeichert.
Deshalb ist kontoStand = kontoStand + 25; sinnvoll, obwohl es keine mathematische Gleichung ist.
Trace / Laufspur anzeigen
| Schritt | Auswertung | Wert von kontoStand |
|---|---|---|
| Initialisierung | 100 wird gespeichert |
100 |
| rechte Seite | kontoStand + 25 wird zu 125 ausgewertet |
100 |
| Zuweisung | Das Ergebnis wird links gespeichert | 125 |
| Ausgabe | System.out.println(...) liest den aktuellen Wert |
125 |
Startzustand und Konsolenausgabe anzeigen
Startzustand
Vor der ersten Anweisung ist kontoStand noch nicht angelegt. Nach der Initialisierung speichert die Variable 100.
Konsolenausgabe
125
Deutung: Bei einer Zuweisung wird zuerst rechts ausgewertet. Erst danach verändert sich der gespeicherte Wert links.
Dieselbe Zustandslogik steckt im Taschenrechnerkontext: Eingabewerte werden gespeichert, ein Rechenausdruck wird ausgewertet und das Ergebnis ersetzt oder ergänzt einen bisherigen Zustand.
Variablen und Datentypen praktisch prüfen
Nutze die Aufgaben, um zu prüfen, wie Werte eingelesen, gespeichert und mit Operatoren verarbeitet werden.
4. Datentypen in Java: Übersicht der primitiven Typen
Die folgenden acht primitiven Datentypen sind fest in Java definiert. Sie speichern einfache Werte direkt und besitzen feste Größen und Wertebereiche.
| Datentyp | Größe | Wertebereich | Standardwert |
|---|---|---|---|
boolean | JVM-abhängig (logisch 1 Bit) | true, false | false |
char | 16 Bit | U+0000 bis U+FFFF | '\u0000' |
byte | 8 Bit | -128 bis 127 | 0 |
short | 16 Bit | -32.768 bis 32.767 | 0 |
int | 32 Bit | -2.147.483.648 bis 2.147.483.647 | 0 |
long | 64 Bit | -9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807 | 0L |
float | 32 Bit | ca. ±1,4E-45 bis ±3,4E+38 | 0.0f |
double | 64 Bit | ca. ±4,9E-324 bis ±1,7E+308 | 0.0d |
5. Primitive Datentypen und Objekte sauber unterscheiden
Primitive Typen speichern unmittelbare Einzelwerte (z. B. Zahl, Zeichen, Wahrheitswert). Bei Referenztypen verweist eine Variable dagegen auf ein Objekt, das intern mehrere Daten und ggf. Methodenbezug zusammenfasst.
int punkte = 42; // primitiver Wert liegt direkt vor
int[] messwerte = {3, 5, 8}; // Variable speichert Referenz auf ein Array-Objekt
String name = "Lea"; // Referenz auf ein String-Objekt
Diese Unterscheidung ist für spätere Kapitel zentral: Arrays und andere Datenstrukturen arbeiten mit Referenzen auf Objekte, während numerische Berechnungen häufig auf primitiven Typen stattfinden.
6. Typumwandlung
Bei der Typumwandlung wird ein Wert in einen anderen Datentyp überführt. Java unterscheidet automatische (implizite) Umwandlung und explizites Casting.
Automatische (implizite) Umwandlung
int anzahl = 7;
double alsDouble = anzahl; // int -> double
float alsFloat = anzahl; // int -> float
Arithmetische Beförderung bei kleinen Ganzzahltypen
byte a = 10;
short b = 20;
int summe = a + b; // byte/short werden in Ausdrücken zu int
Explizite Umwandlung (Casting)
double preis = 19.99;
int euro = (int) preis; // 19, Nachkommastellen fallen weg
long gross = 4_000_000_000L;
int klein = (int) gross; // Überlauf möglich
float note = 2.7f;
int ganzzahl = (int) note; // 2
7. Typische Fehlvorstellungen
Der Operator = wird oft als mathematische Gleichheit interpretiert.
In Java bedeutet er Zuweisung: Der rechte Ausdruck wird ausgewertet und sein Ergebnis links gespeichert.
Ebenso verbreitet ist die Annahme, der Datentyp sei nur „Beschriftung“. Tatsächlich bestimmt der Typ, welche Werte zulässig sind, wie sie gespeichert werden und ob eine Umwandlung automatisch oder nur per Casting möglich ist.
Variablenarbeit, Typsystem und Typumwandlung greifen direkt ineinander. Diese Grundlage ermöglicht es, in den folgenden Kapiteln Ausdrücke und Bedingungen zu formulieren und daraus eine präzise Ablaufsteuerung über Kontrollstrukturen abzuleiten.
Operatoren und logische Ausdrücke
Rechnen, vergleichen und Bedingungen formulieren
Rechnen, vergleichen und Bedingungen formulieren
Variablen und Datentypen liefern die Wertebasis. Operatoren verknüpfen diese Werte zu Berechnungen, Vergleichen und Bedingungen.
1. Konzeptklärung: Ausdruck als auswertbare Struktur
Ein Ausdruck kombiniert Werte, Variablen, Konstanten und Operatoren zu einer auswertbaren Einheit. Das Ergebnis eines Ausdrucks hat einen Datentyp, zum Beispiel numerisch oder boolesch. Operatoren sind damit nicht nur Rechenzeichen, sondern zentrale Bausteine zur Formulierung von Berechnungen und Bedingungen.
2. Strukturelle Einordnung: Ausdrücke im Programmablauf
Arithmetische Ausdrücke erzeugen numerische Ergebnisse, Vergleichsausdrücke erzeugen Wahrheitswerte, und logische Ausdrücke verknüpfen Wahrheitswerte zu komplexeren Bedingungen. Damit bilden sie die fachliche Brücke zwischen Datenverarbeitung und Ablaufsteuerung.
3. Formale Umsetzung: Operatorgruppen, Priorität und Klammerung
Typische arithmetische Operatoren sind +, -, *, / und %.
Vergleichsoperatoren sind unter anderem ==, !=, <, <=, >, >=.
Logische Operatoren wie &&, || und ! arbeiten auf booleschen Werten.
Klammern steuern die Auswertungsreihenfolge explizit und reduzieren Mehrdeutigkeiten.
public class OperatorenDemo {
public static void main(String[] args) {
int a = 8;
int b = 3;
int summe = a + b * 2; // arithmetischer Ausdruck
boolean istGleich = (a == b); // Vergleichsausdruck
boolean istGueltig = (a > b) && (b > 0); // logischer Ausdruck
System.out.println(summe);
System.out.println(istGleich);
System.out.println(istGueltig);
}
}
4. Beispielanalyse: numerisches vs. boolesches Ergebnis
a + b * 2 liefert einen numerischen Wert.
a == b liefert den Wahrheitswert true oder false.
(a > b) && (b > 0) verknüpft zwei boolesche Teilausdrücke zu einer Gesamtbedingung,
die später in if- oder while-Strukturen verwendet werden kann.
| Auswertungsschritt | Teilausdruck | Ergebnis | Typ |
|---|---|---|---|
| 1 | a > b mit a = 8, b = 3 |
true |
boolean |
| 2 | b > 0 mit b = 3 |
true |
boolean |
| 3 | true && true |
true |
boolean |
Vorbereitete Fallvarianten anzeigen
| Fall | a |
b |
a > b |
b > 0 |
Gesamt |
|---|---|---|---|---|---|
| A | 8 | 3 | true | true | true |
| B | 2 | 3 | false | true | false |
| C | 8 | -1 | true | false | false |
Beispielausgabe des Programms anzeigen
14 false true
Deutung: Der boolesche Ausdruck entscheidet noch keinen Programmzweig. Er liefert den Wahrheitswert, den if oder while anschließend zur Steuerung des Ablaufs verwendet.
Ausdrücke sind auswertbare Strukturen: Manche liefern Zahlen, andere Wahrheitswerte. Ein Taschenrechnerprogramm nutzt beides zugleich, etwa wenn ein Rechenzeichen geprüft, eine Division durch Null verhindert oder ein zulässiger Wertebereich abgesichert wird.
5. Logische Operatoren in Bedingungen
Sobald Bedingungen aus mehreren Teilaussagen bestehen, werden logische Operatoren zur Verknüpfung benötigt.
Sie entscheiden, ob eine Gesamtbedingung in Kontrollstrukturen wie if, while oder for
als true oder false ausgewertet wird.
| Name | Java-Notation | Java-Beispiel |
|---|---|---|
| Logical and | && | (sum > min) && (sum < max) |
| Logical or | || | (answer == 'y') || (answer == 'Y') |
| Logical not | ! | !(number < 0) |
Die Tabelle zeigt die typische Rollenverteilung: && fordert, dass beide Teilbedingungen gelten,
|| akzeptiert mindestens eine zutreffende Bedingung, und ! negiert einen vorhandenen Wahrheitswert.
6. Wahrheitstabelle für &&, || und !
Wahrheitstabellen helfen dabei, das Verhalten logischer Operatoren exakt zu überprüfen. Gerade bei verschachtelten Bedingungen in Schleifen und Verzweigungen lässt sich so vorab prüfen, welche Kombinationen zu einer Ausführung des jeweiligen Blocks führen.
| A | B | A && B | A || B | !(A) |
|---|---|---|---|---|
true | true | true | true | false |
true | false | false | true | false |
false | true | false | true | true |
false | false | false | false | true |
Für die Praxis heißt das: Bedingungen lassen sich aus mehreren Teilaussagen zusammensetzen,
um Programmabläufe präzise zu steuern. Das ist zentral für Grenzprüfungen in if-Anweisungen,
Abbruchkriterien in while-Schleifen und kombinierte Laufbedingungen in for-Schleifen.
Bedingungen im Java-Werkzeug testen
Hier werden arithmetische Operatoren, Stringvergleich, Vergleichsoperatoren und logische Verknüpfung verbunden. Strings werden mit .equals(...) verglichen, nicht mit ==.
7. Typische Fehlvorstellungen
Ein häufiger Fehler ist die Verwechslung von = (Zuweisung) und == (Vergleich).
Dadurch wird statt einer Bedingung unbeabsichtigt ein Wert zugewiesen oder ein Syntaxfehler erzeugt.
Ebenso wird oft angenommen, jeder Ausdruck liefere eine Zahl. Vergleichs- und logische Ausdrücke liefern jedoch boolesche Werte und sind damit direkt als Bedingungen interpretierbar.
Ohne Klammerung wird die Priorität von Operatoren häufig falsch eingeschätzt. Explizite Klammern sichern die beabsichtigte Auswertungsreihenfolge.
Die klare Trennung zwischen Berechnung, Vergleich und logischer Verknüpfung macht sichtbar, wie Ausdrücke als Grundlage für Verzweigungen und Schleifen dienen und damit die Ablaufsteuerung ermöglichen.
Kontrollstrukturen
Abläufe steuern und mit Struktogrammen systematisch modellieren
Abläufe steuern und mit Struktogrammen systematisch modellieren
Logische Ausdrücke führen direkt zur Steuerung vollständiger Abläufe: aus einzelnen Bedingungen entstehen geordnete Folgen von Anweisungen, Entscheidungen und Wiederholungen.
A) Einführung: Was sind Kontrollstrukturen?
Kontrollstrukturen ordnen einzelne Anweisungen zu nachvollziehbaren Abläufen. Sie legen fest, ob Anweisungen nacheinander ausgeführt werden (Sequenz), ob zwischen Alternativen entschieden wird (Verzweigung) oder ob Schritte wiederholt werden (Schleife). Bedingungen werden dabei in Verzweigungen und Schleifen ausgewertet: Ihr Wahrheitswert entscheidet, welcher Zweig läuft oder ob eine Wiederholung fortgesetzt wird. Damit entsteht zunächst kontrollierte Ablaufmodellierung, noch keine formale Algorithmusanalyse.
B) Struktogramm-Notation (grundlegend)
Struktogramme beschreiben Ablauflogik in Blöcken. Die Notation ist sprachneutral und passt direkt zum eingebundenen Struktogramm-Tool: Sequenz als Folge von Blöcken, Verzweigung als geteilte Entscheidung, Schleifen als wiederholte Blöcke mit Bedingung. Dadurch wird sichtbar, aus welchen elementaren Formen spätere algorithmische Verfahren aufgebaut werden können.
Werkzeugpfad: Code und Struktogramm verbinden
Im Struktogramm-Werkzeug wird Kontrollfluss als Handlungsschicht sichtbar. Arbeite in beide Richtungen:
- Java-Code in ein Struktogramm übersetzen.
- Das Struktogramm lesen und den Ablauf als Trace beschreiben.
- Die dargestellte Verzweigung oder Schleife zurück in Java-Code übertragen.
Struktogramm: Grundnotation
1) Bedingte Anweisung (if / if-else)
Erklärung: Eine Bedingung steuert, welcher Pfad ausgeführt wird. Bei if-else sind zwei Pfade explizit vorhanden.
if (temperatur < 0) {
status = "Frost";
} else {
status = "kein Frost";
}
Struktogramm-Konvention: Verzweigung
Leselogik: Was passiert hier? Es wird genau ein Zweig ausgeführt. Wie liest man das Struktogramm? Erst Bedingung prüfen, dann den passenden Pfad verfolgen.
2) While-Schleife
Erklärung: Die while-Schleife ist kopfgesteuert. Die Bedingung wird vor jedem Durchlauf geprüft.
int i = 0;
while (i < 3) {
System.out.println(i);
i++;
}
Struktogramm-Konvention: kopfgesteuerte Schleife
Leselogik: Was passiert hier? Der Block läuft wiederholt, solange die Bedingung wahr bleibt. Wie liest man das Struktogramm? Bedingung oben, dann Schleifenkörper, danach Rücksprung zur Bedingung.
Trace / Laufspur anzeigen
| Durchlauf | i vor Prüfung |
Bedingung i < 3 |
Ausgabe | i danach |
|---|---|---|---|---|
| 1 | 0 | true | 0 | 1 |
| 2 | 1 | true | 1 | 2 |
| 3 | 2 | true | 2 | 3 |
| 4 | 3 | false | keine | 3 |
Konsolenausgabe anzeigen
0 1 2
Deutung: Die Schleife wiederholt nicht blind. Vor jedem Durchlauf wird ein aktueller Zustand geprüft. Erst wenn die Bedingung false wird, endet der Ablauf.
3) For-Schleife
Erklärung: Die for-Schleife bündelt Initialisierung, Bedingung und Schrittweite. Sie ist die typische Zählschleife und bereitet die Iteration über Arrays vor.
int[] werte = {7, 4, 9};
for (int i = 0; i < werte.length; i++) {
System.out.println(werte[i]);
}
Struktogramm-Konvention: Zählschleife
Leselogik: Was passiert hier? Jeder Index wird genau einmal besucht. Wie liest man das Struktogramm? Ein Zählbereich steuert die Wiederholung, der Körper verarbeitet pro Durchlauf ein Element.
Wiederholungen als Laufspur üben
Die Aufgaben machen sichtbar, wie Bedingungen, Zustandsänderung und Wiederholung zusammenarbeiten.
| Ablaufproblem | Passende Struktur | Beispielkontext |
|---|---|---|
| Wiederholen, bis ein Ziel erreicht oder aufgegeben wird | while |
Zahlenratespiel |
| Eingabe wiederholen, bis sie gültig ist | while oder do-while |
gültige Zahl, gültiges Rechenzeichen |
| Feste Anzahl von Aufgaben bearbeiten | for |
Mathe-Challenge mit zehn Aufgaben |
| Solange weiterspielen, wie Antworten richtig sind | while |
Endless-Mode |
4) Do-While-Schleife
Erklärung: Die do-while-Schleife ist fußgesteuert. Der Schleifenkörper wird mindestens einmal ausgeführt.
int versuche = 0;
do {
versuche++;
} while (versuche < 1);
Struktogramm-Konvention: fußgesteuerte Schleife
Leselogik: Was passiert hier? Ein erster Durchlauf ist garantiert, erst dann wird geprüft. Wie liest man das Struktogramm? Zuerst den Block, dann die Bedingung als Fortsetzungsentscheidung.
5) Switch-Anweisung
Erklärung: switch modelliert eine Mehrfachverzweigung und ersetzt lange Ketten verschachtelter if-Abfragen.
switch (note) {
case 1: text = "sehr gut"; break;
case 2: text = "gut"; break;
default: text = "weitere";
}
Struktogramm-Konvention: Mehrfachverzweigung
Leselogik: Was passiert hier? Genau ein passender Fall wird gewählt, sonst der Default-Pfad. Wie liest man das Struktogramm? Von der Auswahlbedingung zu genau einem der Alternativpfade.
Brücke zur strukturierten Verarbeitung
Sequenz, Verzweigung und Schleife sind die elementaren Formen, aus denen verlässliche Verarbeitungsabläufe entstehen. Struktogramme machen diese Abläufe unabhängig von einer konkreten Programmiersprache sichtbar. Darauf aufbauend werden Kontrollstrukturen im nächsten Kapitel als wiederverwendbare Teilabläufe in Methoden gekapselt.
EVA-Prinzip als Grundmodell für Programme
Bereits erarbeitete Bausteine als Eingabe, Verarbeitung und Ausgabe zusammenlesen
Bereits erarbeitete Bausteine als Eingabe, Verarbeitung und Ausgabe zusammenlesen
Nach Einführung, Datentypen, Operatoren und Kontrollstrukturen ordnet das EVA-Prinzip die bekannten Bausteine zu einem gemeinsamen Funktionsmodell. EVA ist hier kein Neueinstieg, sondern eine rückblickende Strukturformel für vollständige Programmabläufe: Eingaben werden gelesen, Verarbeitung wird gekapselt und Ausgaben werden sichtbar gemacht.
1. Ordnungsmodell: Bekannte Sprachelemente funktional bündeln
- Eingabe: Daten über Konsole, GUI-Elemente oder andere Quellen erfassen.
- Verarbeitung: Werte mit Variablen und Datentypen speichern, mit Operatoren berechnen und über Bedingungen, Kontrollstrukturen und Methoden auswerten.
- Ausgabe: Ergebnisse strukturiert darstellen, weitergeben oder in der Oberfläche zurückmelden.
Die folgende Übersicht zeigt, wie dieses Ordnungsmodell in verschiedenen Programmkontexten sichtbar wird.
| Kontext | Eingabe | Verarbeitung | Ausgabe |
|---|---|---|---|
| Konsolenprogramm | Scanner liest Werte |
Methode berechnet oder prüft | println zeigt Ergebnis |
| GUI-Programm | TextField und Button |
Event-Handler ruft Methode auf | Label zeigt Ergebnis |
| Datenprogramm | Array mit Messwerten oder Noten | Schleife/Methode bildet Statistik | Durchschnitt, Minimum, Maximum |
Dadurch werden einzelne Kenntnisse nicht isoliert gelesen, sondern als zusammenhängender Ablauf: von der Datenerfassung über eine Methode oder Folge von Methoden bis zur begründeten Ausgabe. Die Verarbeitung ist der Ort, an dem später algorithmische Verfahren stehen können; in E3 wird sie zunächst als klar benannte Verarbeitungsroutine aufgebaut.
EVA ist also nicht an die Konsole gebunden. In Konsolenprogrammen liest Scanner Eingaben,
in GUI-Programmen liefern Komponenten Eingabezustände, und in Datenprogrammen kann ein Array die Eingabebasis bilden.
Die Verarbeitung sollte in allen Fällen als eigene, prüfbare Methode lesbar bleiben.
EVA mit Methoden praktisch prüfen
Die Aufgabe zeigt, wie Eingaben gelesen, Berechnungen in Methoden gekapselt und Ergebnisse ausgegeben werden.
Beispiel: Sequenzdiagramm / GUI-Ereignisfolge
Auch in grafischen Oberflächen bleibt die EVA-Logik erhalten: Ein Ereignis löst Verarbeitung aus, die anschließend in einer sichtbaren Ausgabe endet.
Beispiel: Namen einlesen und begrüßen
import java.util.Scanner;
public class EvaBegruessung {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Wie heißt du? ");
String name = scanner.nextLine();
String gruss = "Hallo, " + name + "!";
System.out.println(gruss);
}
}
- Eingabe:
scanner.nextLine()liest den Namen ein. - Verarbeitung: Der Begrüßungstext wird mit String-Verkettung aufgebaut.
- Ausgabe:
System.out.println(...)gibt den Text aus.
Beispiel: Zwei Zahlen einlesen und addieren
import java.util.Scanner;
public class EvaAddition {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Erste Zahl: ");
double a = scanner.nextDouble();
System.out.print("Zweite Zahl: ");
double b = scanner.nextDouble();
double summe = a + b;
System.out.println("Summe: " + summe);
}
}
- Eingabe: Zwei Zahlen werden als
doubleeingelesen. - Verarbeitung: Der Operator
+berechnet die Summe. - Ausgabe: Das Ergebnis wird formatiert ausgegeben.
Beispiel: Alter abfragen und mit if auswerten
import java.util.Scanner;
public class EvaAlter {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Wie alt bist du? ");
int alter = scanner.nextInt();
String meldung;
if (alter >= 18) {
meldung = "Du bist volljährig.";
} else {
meldung = "Du bist minderjährig.";
}
System.out.println(meldung);
}
}
- Eingabe: Das Alter wird als Ganzzahl eingelesen.
- Verarbeitung: Eine
if-Kontrollstruktur entscheidet zwischen zwei Meldungen. - Ausgabe: Die passende Meldung wird ausgegeben.
Beispiel: Punktzahl mit Methode bewerten
import java.util.Scanner;
public class EvaBewertung {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Punktzahl: ");
int punkte = scanner.nextInt();
String urteil = bewertePunktzahl(punkte);
System.out.println("Bewertung: " + urteil);
}
public static String bewertePunktzahl(int punkte) {
if (punkte >= 90) {
return "sehr gut";
} else if (punkte >= 75) {
return "gut";
}
return "ausreichend";
}
}
- Eingabe: Die Punktzahl wird eingelesen.
- Verarbeitung: Die Methode
bewertePunktzahl(...)kapselt die Entscheidungslogik und liefert ein Ergebnis zurück. - Ausgabe: Das zurückgegebene Urteil wird ausgegeben.
2. Fachliche Brücke
Im nächsten Schritt wird die Verarbeitung systematisch in Methoden gegliedert. So kann dieselbe Fachlogik in einem Konsolenprogramm, in einem Test oder später in einer GUI genutzt werden. In ereignisgesteuerten Programmen koppelt ein Event-Handler Eingabezustände, Verarbeitungsmethode und Ausgabe wieder nach dem EVA-Muster.
Methoden, Strukturierung und erste Modellierung
Programme in sinnvoll gegliederte Bausteine zerlegen
Programme in sinnvoll gegliederte Bausteine zerlegen
Kontrollstrukturen beschreiben den Ablauf, Methoden kapseln zusammengehörige Folgen von Anweisungen zu wiederverwendbaren Teilaufgaben.
1. Was ist eine Methode?
Eine Methode ist ein benannter, wiederverwendbarer Ablaufblock innerhalb einer Klasse. Sie wird nur ausgeführt, wenn sie über einen Methodenaufruf gestartet wird. Damit werden Programme nicht als „ein großer Block“, sondern als geordnete Teilaufgaben aufgebaut. In E3 steht Methode deshalb zunächst für eine benannte Teilaufgabe beziehungsweise eine wiederverwendbare Verarbeitungsroutine. Der volle objektorientierte Methodenbegriff als Verhalten von Objekten wird in Q1.1 systematisch entwickelt.
2. Warum nutzt man Methoden?
Methoden verbessern Lesbarkeit, Wartbarkeit und Wiederverwendbarkeit. Wenn dieselbe Logik mehrfach gebraucht wird, wird sie einmal definiert und anschließend an mehreren Stellen aufgerufen. So entsteht die erste konkrete Form, in der ein Verfahren benannt, abgegrenzt und wiederverwendet wird. Das bereitet den Algorithmusgedanken vor, ohne hier bereits Such- und Sortieralgorithmen zu analysieren.
3. Aufbau einer Methode: Methodenkopf und Methodenrumpf
Eine Methodendeklaration besteht aus Methodenkopf und Methodenrumpf. Im Kopf stehen Sichtbarkeit, ggf. static, Rückgabetyp, Name und Parameterliste. Im Rumpf steht die eigentliche Verarbeitung.
public static int berechneRabatt(int preis, int prozent) {
int rabatt = preis * prozent / 100;
return rabatt;
}
Leselogik: public static int berechneRabatt(int preis, int prozent) ist der Kopf.
Der Block zwischen { und } ist der Rumpf.
berechneRabatt
int preis, int prozent
int als berechneter Rabatt
Eine Methode wirkt damit wie eine fachliche Schnittstelle: Außen ist sichtbar, welche Eingaben erwartet werden, wie die Routine heißt und welcher Ergebnistyp zurückkommt. Die konkrete Verarbeitung bleibt im Rumpf gekapselt.
Methodenaufruf simulieren
Aufrufstelle
int r = berechneRabatt(100, 20);
Die Argumente sind 100 und 20.
Endzustand
return gibt 20 zurück.
Die Aufrufstelle speichert danach r = 20.
| Phase | Wirkung |
|---|---|
| Argumente | An der Aufrufstelle stehen 100 und 20. |
| Parameterbindung | In der Methode gilt preis = 100, prozent = 20. |
| Verarbeitung | 100 * 20 / 100 wird zu 20 ausgewertet. |
| lokaler Wert | rabatt = 20 existiert innerhalb der Methode. |
| Rückgabe | return rabatt; gibt 20 an die Aufrufstelle zurück. |
| Nutzung | int r speichert den zurückgegebenen Wert. |
Deutung: Parameter sind lokale Namen innerhalb der Methode. Der Rückgabewert verlässt die Methode erst durch return und muss an der Aufrufstelle genutzt oder gespeichert werden.
| Methodenkontext | Typische Schnittstelle | Fachliche Funktion |
|---|---|---|
| Punktbewertung | bewertePunktzahl(int punkte) | Grenzwerte prüfen und Urteil zurückgeben |
| Quaderberechnung | berechneVolumen(double a, double b, double c) | gleiche Eingaben für unterschiedliche Rückgaben nutzen |
| Geometrie | berechneRaumdiagonale(double a, double b, double c) | Formel als benannte Verarbeitung kapseln |
| Anhalteweg | berechneAnhalteweg(double v) | Fachlogik später aus GUI oder Konsole aufrufen |
Methodenaufrufe im Java-Werkzeug nachvollziehen
Parameterbindung, Rückgabewerte und lokale Verarbeitung lassen sich im Trace nachvollziehen.
4. Methoden aufrufen: Name + Klammern
Eine Methode wird über ihren Namen mit Klammern aufgerufen. Einmal definierte Methoden können mehrfach aufgerufen werden, auch mit unterschiedlichen Eingaben.
public static void main(String[] args) {
begruessung();
begruessung();
}
public static void begruessung() {
System.out.println("Willkommen im Kurs E3.");
}
Die Methode begruessung() besitzt keine Parameter und keinen Rückgabewert.
Sie führt beim Aufruf nur eine Aktion aus.
5. Parameter: Eingaben für eine Teilaufgabe
Parameter machen Methoden flexibel. Statt feste Werte im Methodenrumpf zu verwenden, werden die Werte beim Aufruf übergeben.
public static void ausgabeTicketpreis(int preis) {
System.out.println("Ticketpreis: " + preis + " €");
}
public static void main(String[] args) {
ausgabeTicketpreis(29);
ausgabeTicketpreis(45);
}
Die Methode bleibt gleich, nur das Argument ändert sich. So wird dieselbe Logik für verschiedene Situationen genutzt.
6. Rückgabewerte, return und void
Methoden mit Rückgabetyp liefern einen Rückgabewert an die Aufrufstelle zurück.
Das Ergebnis wird über return zurückgegeben.
Bei void-Methoden steht die Aktion im Vordergrund, nicht ein berechneter Rückgabewert.
// Methode mit Rückgabewert
public static int berechneGesamtpreis(int preisProTicket, int anzahl) {
return preisProTicket * anzahl;
}
// void-Methode
public static void zeigeHinweis() {
System.out.println("Bitte Anzahl überprüfen.");
}
public static void main(String[] args) {
int gesamt = berechneGesamtpreis(40, 3);
System.out.println("Gesamtpreis: " + gesamt);
zeigeHinweis();
}
Modellierungsbezug: Berechnungen (z. B. Preise, Zeiten, Indizes) eignen sich oft für Methoden mit Rückgabewert,
während Statusmeldungen oder Ausgaben häufig als void-Methoden formuliert werden.
Beispiel: Verarbeitung unabhängig vom Eingabekanal
Die Methode enthält die fachliche Verarbeitung. Sie kann aus main heraus oder später aus einem Event-Handler aufgerufen werden.
public static String bewertePunktzahl(int punkte) {
if (punkte >= 90) {
return "sehr gut";
} else if (punkte >= 75) {
return "gut";
}
return "ausreichend";
}
// Konsolenprogramm:
int konsolenPunkte = 82;
String urteil = bewertePunktzahl(konsolenPunkte);
System.out.println("Bewertung: " + urteil);
// GUI-Event-Handler:
int guiPunkte = Integer.parseInt(eingabe.getText());
ausgabe.setText("Bewertung: " + bewertePunktzahl(guiPunkte));
Die Eingabe kann aus der Konsole oder aus einer GUI-Komponente stammen. Die Verarbeitungsroutine bleibt dieselbe.
7. static im aktuellen E3-Kontext
In E3 werden viele Beispiele innerhalb einer Klasse mit main umgesetzt.
Damit main eine Methode direkt aufrufen kann, wird sie in diesem Kontext meist als static notiert.
Didaktisch genügt hier: static bedeutet, dass die Methode zur Klasse gehört und ohne erzeugtes Objekt nutzbar ist.
Das ist eine Arbeitsregel für den Einstieg, keine vollständige OOP-Erklärung.
8. Methoden als Strukturierungsprinzip
Größere Programme werden in fachlich sinnvolle Teilaufgaben zerlegt: Eingaben prüfen, Werte berechnen, Ergebnisse ausgeben. Dadurch wird der Programmablauf besser lesbar und leichter wartbar. Diese Denkweise verbindet Methoden direkt mit Kontrollstrukturen, Datenstrukturen und dem späteren Algorithmus-Begriff. Auch im Struktogramm kann ein Methodenaufruf als Blockaufruf modelliert werden.
public static boolean istGueltigerIndex(int index, int[] daten) {
return index >= 0 && index < daten.length;
}
public static int leseWertSicher(int index, int[] daten) {
if (istGueltigerIndex(index, daten)) {
return daten[index];
}
return -1;
}
Hier ruft eine Methode eine andere auf.
Kontrollstruktur (if) und Datenstruktur (int[]) werden sauber in Teilaufgaben gegliedert.
9. Methodenüberladung in tragfähigem Umfang
Bei der Methodenüberladung haben Methoden denselben Namen, aber unterschiedliche Parameterlisten. Der Name beschreibt die fachliche Aufgabe, die Parameterliste die konkrete Variante.
public static int addiere(int a, int b) {
return a + b;
}
public static double addiere(double a, double b) {
return a + b;
}
Die Aufrufe addiere(3, 4) und addiere(2.5, 1.5) wählen automatisch die passende Methode.
Für E3 reicht dieses Grundverständnis; weiterführende Spezialfälle folgen später.
10. Typische Fehlvorstellungen (kompakt)
Methoden werden nicht automatisch ausgeführt, sondern nur durch Aufruf.
Parameter sind lokal und keine globalen Variablen.
Ein Rückgabewert entsteht nur bei Methoden mit passendem Rückgabetyp und return.
Methodenüberladung unterscheidet sich über die Parameterliste, nicht über den Methodennamen allein.
So strukturierte Teilaufgaben arbeiten in der Praxis häufig auf größeren Datenmengen; dafür sind Arrays und Strings als Datenstrukturen zentral.
Datenstrukturen
Arrays und Strings als strukturierte Grundlage für algorithmisches Arbeiten
Arrays und Strings als strukturierte Grundlage für algorithmisches Arbeiten
Nach der methodischen Strukturierung steht die Datenperspektive im Mittelpunkt: Die gleiche Problemstellung wird nicht mehr mit Einzelwerten, sondern mit geordneten Datensammlungen bearbeitet.
A) Einführung: Warum Datenstrukturen?
Einzelne Variablen reichen nur für einzelne Werte. Sobald mehrere zusammengehörige Informationen verarbeitet werden sollen (z. B. mehrere Messwerte oder ein ganzer Text), braucht man Datenstrukturen. Sie speichern nicht nur mehrere Daten, sondern ordnen sie so, dass gezielter Zugriff, systematisches Durchlaufen und algorithmische Verarbeitung möglich werden.
Damit entsteht die fachliche Entwicklung dieses Kapitels: von einzelnen Variablen hin zu strukturierten Datensammlungen und weiter zur algorithmischen Verarbeitung.
B) Arrays als zentrale Datenstruktur
Ein Array speichert mehrere Werte gleichen Typs unter einem Namen.
Die Länge ist nach der Erzeugung fest. Auf einzelne Elemente greift man über den
Index zu. Indizes beginnen bei 0;
der letzte gültige Index ist immer array.length - 1.
// Initialisierung mit fester Länge und Startwerten
int[] zahlen = {10, 20, 30, 40};
// Zugriff über Index
int ersterWert = zahlen[0];
int dritterWert = zahlen[2];
| Index | 0 |
1 |
2 |
3 |
|---|---|---|---|---|
| Wert | 10 |
20 |
30 |
40 |
zahlen[0] liefert 10, zahlen[2] liefert 30;
zahlen[4] wäre ungültig, weil die vier Werte nur die Indizes 0 bis 3 besitzen.
Der Nutzen von Arrays liegt nicht nur in der Speicherung, sondern vor allem im geordneten Zugriff: Positionen sind eindeutig adressierbar und können deshalb gezielt geprüft, verändert oder verglichen werden.
// Durchlaufen eines Arrays mit for-Schleife
for (int i = 0; i < zahlen.length; i++) {
System.out.println("Index " + i + " -> " + zahlen[i]);
}
| Durchlauf | i |
Bedingung i < zahlen.length |
Zugriff | Ausgabe |
|---|---|---|---|---|
| 1 | 0 | true | zahlen[0] | 10 |
| 2 | 1 | true | zahlen[1] | 20 |
| 3 | 2 | true | zahlen[2] | 30 |
| 4 | 3 | true | zahlen[3] | 40 |
| 5 | 4 | false | kein Zugriff | keine |
Deutung: Die Schleife besucht jeden gültigen Index genau einmal. Bei Noten-, Punkt- oder Messwertlisten ist diese Laufspur die Grundlage für Durchschnitt, Minimum, Maximum und Zählungen.
Arrays im Java-Werkzeug auswerten
Die Aufgaben nutzen Indexzugriff, array.length, Schleifen und Auswertungsmuster.
Ausblick: Arrays mit java.util.Arrays auswerten
java.util.Arrays ist eine Hilfsklasse mit statischen Methoden zur Arbeit mit Arrays.
Dieser Block ist ein optionaler Ausblick; die Methoden sind nützlich, aber nicht Pflichtstoff der aktuellen Unterrichtsphase.
import java.util.Arrays;
int[] zahlen = {40, 10, 30, 20};
System.out.println(Arrays.toString(zahlen));
Arrays.sort(zahlen);
int position = Arrays.binarySearch(zahlen, 30);
Arrays.toString(array)erzeugt eine lesbare Ausgabe der Array-Inhalte.Arrays.sort(array)sortiert ein Array.Arrays.binarySearch(array, wert)sucht in einem sortierten Array nach einem Wert.
Wichtig: binarySearch setzt ein sortiertes Array voraus. Wird vorher nicht sortiert,
ist das Ergebnis für Lernende fachlich nicht verlässlich interpretierbar.
Das Durchlaufen (Iterieren) über Arrays verbindet dieses Kapitel direkt mit den Kontrollstrukturen aus Kapitel 4.
C) Strings als besondere Datenstruktur für Text
Ein String ist eine Zeichenfolge. Die Java-8-Dokumentation beschreibt
String als Klasse für Zeichenketten und nennt Methoden zum Untersuchen einzelner Zeichen,
zum Vergleichen, Suchen, Ausschneiden und Umformen von Text.
Auch bei Strings beginnt die Indizierung bei 0. Der letzte gültige Index ist
string.length() - 1. Einzelne Zeichen werden mit charAt(index) gelesen.
Anders als Arrays sind Strings unveränderlich (immutable).
String kurs = "Informatik";
int laenge = kurs.length();
char erstesZeichen = kurs.charAt(0);
char fuenftesZeichen = kurs.charAt(4);
String anfang = kurs.substring(0, 5); // "Infor"
| Index | 0 |
1 |
2 |
3 |
4 |
|---|---|---|---|---|---|
| Zeichen | I |
n |
f |
o |
r |
Bei String kurs = "Informatik"; liefert kurs.charAt(0) das Zeichen I,
kurs.charAt(4) das Zeichen r. kurs.length() liefert die Anzahl der Zeichen,
nicht den letzten Index.
| Ausdruck | Deutung | Ergebnis |
|---|---|---|
kurs.substring(0, 5) |
Startindex 0 ist enthalten, Endindex 5 ist ausgeschlossen |
"Infor" |
kurs.indexOf("mat") |
liefert die erste Fundstelle des Teilstrings | 5 |
kurs.indexOf("@") |
gesuchtes Zeichen kommt nicht vor | -1 |
Der Rückgabewert -1 ist ein Diagnosefall: Vor einem substring-Zugriff muss geprüft werden,
ob die gesuchte Position überhaupt gefunden wurde. Sonst entstehen ungültige Indizes.
String-Befehle im Kontext: Prüfen, Finden, Ausschneiden, Umformen
In den Arbeitsaufträgen werden Strings nicht nur gespeichert, sondern geprüft und zerlegt: Bei Benutzernamen geht es um Länge, Unterstrich und Namensbestandteile; bei E-Mail-Adressen um @-Zeichen, Punkte und Teilstrings. String-Methoden sind dafür Werkzeuge, mit denen Text als geordnete Zeichenfolge untersucht wird.
| Methode | Wozu? | Kontextbeispiel | Rückgabe |
|---|---|---|---|
length() | Länge prüfen | username.length() >= 8 | int |
isEmpty() | leere Eingabe prüfen | eingabe.isEmpty() | boolean |
trim() | Leerzeichen am Anfang/Ende entfernen | eingabe.trim() | String |
equals(...) | Inhalte vergleichen | eingabe.equals("ende") | boolean |
contains(...) | Teiltext suchen | email.contains("@") | boolean |
indexOf(...) | erste Position finden | int at = email.indexOf("@"); | int |
lastIndexOf(...) | letzte Position finden | email.lastIndexOf("@") | int |
substring(start, ende) | Teilstring ausschneiden | email.substring(0, at) | String |
charAt(index) | einzelnes Zeichen lesen | text.charAt(i) | char |
replace(...) | Textstellen ersetzen | text.replace(" ", "_") | String |
toUpperCase() / toLowerCase() | Schreibweise vereinheitlichen | name.toLowerCase() | String |
String email = "lea.mueller@example.de";
int at = email.indexOf("@");
boolean genauEinAt = at == email.lastIndexOf("@");
int punktNachAt = email.indexOf(".", at);
if (at > 0 && genauEinAt && punktNachAt > at + 1) {
String benutzer = email.substring(0, at);
String domain = email.substring(at + 1, punktNachAt);
System.out.println("Benutzer: " + benutzer);
System.out.println("Domain: " + domain);
} else {
System.out.println("Die E-Mail-Adresse ist formal nicht gültig.");
}
Für die Arbeit mit Strings ist vor allem wichtig:
- Strings sind Objekte und unveränderlich (
immutable). - Methoden wie
replace(...),toLowerCase(),trim()odersubstring(...)verändern den ursprünglichen String nicht. - Soll das Ergebnis weiterverwendet werden, muss es gespeichert werden.
String name = " Lea ";
name.trim(); // Ergebnis wird verworfen
name = name.trim(); // Ergebnis wird gespeichert
Strings sind für Text optimiert und bieten dafür eigene Operationen. Gleichzeitig bleiben sie strukturiert genug, um Zeichenfolgen systematisch zu durchlaufen.
// Iteration über alle Zeichen eines Strings
for (int i = 0; i < kurs.length(); i++) {
System.out.println(kurs.charAt(i));
}
- Indizes beginnen bei
0. - Der letzte gültige Index ist immer Länge minus eins.
indexOf(...)liefert-1, wenn der gesuchte Text nicht vorkommt.substring(start, ende)enthältstart, aber nichtende.substring(start, ende)kann Fehler auslösen, wenn die Indizes ungültig sind.- Strings sind unveränderlich; Methoden erzeugen meist neue Strings.
- Arrays haben nach der Erzeugung eine feste Länge.
array.lengthist ein Attribut ohne Klammern,string.length()ist eine Methode mit Klammern.
D) Gemeinsamkeiten von Arrays und Strings
- Beide sind geordnet.
- Beide können über Indizes betrachtet werden.
- Beide lassen sich mit Schleifen durchlaufen.
- Der Indexzugriff ist die Brücke zur algorithmischen Verarbeitung.
- Unterschied: Arrays können Elemente verändern, Strings nicht direkt.
Diese gemeinsame Strukturperspektive ist entscheidend: Lernende betrachten Arrays und Strings nicht als isolierte Einzelthemen, sondern als Varianten derselben Grundidee „strukturierte Daten“.
E) Einordnung: primitive Datentypen, komplexe Strukturen und Ausblick
Im Unterschied zu primitiven Datentypen wie int oder boolean,
die jeweils einen einzelnen Wert speichern, repräsentieren Arrays und Strings
mehrere, strukturierte Werte in einer gemeinsamen Form.
Die Java-8-API stützt diese Einordnung: String bietet Methoden zum Prüfen, Suchen,
Ausschneiden und Umformen von Zeichenfolgen; java.util.Arrays bündelt statische
Hilfsmethoden, etwa für lesbare Ausgabe und elementare Array-Operationen.
Für die nächsten Kapitel ist diese Einordnung zentral: Verarbeitungsroutinen arbeiten häufig auf genau solchen Strukturen, etwa wenn Werte geprüft, gezählt, verändert oder ausgegeben werden. Zugleich ist der Blick nach vorne wichtig: Strings sind in Java Objekte, und komplexere Datenorganisation wird in der Qualifikationsphase systematisch über Objektstrukturen in Q1.1 und über Datenstrukturen in Q1.4 vertieft. Q2.1 ist der passende Anschluss, wenn aus solchen Strukturen ein fachliches Datenmodell entwickelt wird.
Damit ist die Datenbasis gelegt, auf der spätere algorithmische Verfahren in Q1.2 als Such- und Sortierstrategien untersucht werden können.
Grafische Benutzeroberflächen und ereignisgesteuerte Programmierung
Interaktion über Fenster, Eingaben und Aktionen
Interaktion über Fenster, Eingaben und Aktionen
Eine grafische Benutzeroberfläche besteht aus sichtbaren Bausteinen. Einige Bausteine dienen der Eingabe, andere lösen Aktionen aus, wieder andere zeigen Ergebnisse an. Erst durch ihr Zusammenspiel entsteht eine interaktive Anwendung.
Eine GUI ist zugleich Präsentations- und Interaktionsschicht eines Programms: Sie nimmt Eingaben entgegen, macht Zustände sichtbar und löst Verarbeitungsschritte aus. Im Unterschied zur Konsole läuft die Interaktion nicht über eine feste Eingabezeile, sondern über Benutzeraktionen wie Klicks, Auswahlen oder Texteingaben.
Im Beispiel sind die Grundbausteine gut erkennbar: Das Fenster ist der äußere Rahmen der Anwendung. Darin strukturieren Bereiche/Container die Oberfläche in inhaltliche Gruppen. Ein Eingabefeld nimmt Werte auf, eine Schaltfläche (Button) startet eine Aktion, und ein Schriftfeld (Label) zeigt Ergebnisse an.
Im Beispiel werden die Bausteine direkt auf den GUI-Ablauf bezogen: Eingabefelder liefern Werte, die Schaltfläche löst ein Ereignis aus, und Schriftfelder zeigen Ergebnisse. Ein Button ist dabei ein Auslöser, nicht die Verarbeitung selbst.
Nach dem EVA-Einstieg mit Konsolenprogrammen wird dieselbe Grundidee in grafischen Benutzeroberflächen unter Ereignissteuerung umgesetzt. Der Programmablauf ist dabei nicht mehr ausschließlich eine feste Folge von Konsoleneingaben und Ausgaben. Stattdessen wird zuerst eine Oberfläche aufgebaut; danach wartet das Programm auf Ereignisse wie einen Klick.
Eine grafische Benutzeroberfläche besteht aus sichtbaren Komponenten, die als Objekte modelliert sind. Jede Komponente besitzt Eigenschaften, Methoden und einen internen Zustand, der gelesen oder verändert werden kann. Eine GUI verbindet damit Darstellung, Eingabe und Reaktion auf Benutzerereignisse zu einem gemeinsamen Ablauf. In Java-Swing wird die Oberfläche aus Containern und Komponenten zusammengesetzt. In E3 steht dabei nicht professionelle Oberflächengestaltung im Mittelpunkt, sondern das Verstehen dieses Grundprinzips. Klasse, Objekt und Attribut werden hier nur angebahnt; Q1.1 entwickelt diese OOP-Begriffe systematisch weiter. Kurz gefasst: Eine GUI setzt EVA unter Ereignissteuerung um.
Hier kehren die vorherigen Kapitel in einer neuen Umgebung wieder: Variablen erscheinen als Eingabe- und Ausgabezustände, Ausdrücke als Berechnungen, Bedingungen als Prüfungen im Event-Handler, Methoden als Fachlogik und EVA als Ablauf von Benutzeraktion bis Ergebnisanzeige.
1. Oberfläche, Ereignissteuerung und Fachlogik
Eine einfache GUI-Anwendung lässt sich in drei Ebenen denken: Die Oberfläche nimmt Eingaben entgegen und zeigt Ergebnisse, die Ereignissteuerung reagiert auf Benutzeraktionen, und die Fachlogik führt Berechnungen und Prüfungen aus.
| Ebene | Aufgabe |
|---|---|
| Oberfläche | Anzeigen, Eingaben aufnehmen und Zustände sichtbar machen |
| Ereignissteuerung | Reaktion registrieren und beim Ereignis ausführen |
| Fachlogik | Berechnungen, Prüfungen und Regeln unabhängig von der Oberfläche formulieren |
GUI-Komponenten sind nicht die Fachlogik. Sie liefern Zustände oder zeigen Ergebnisse; die Verarbeitung bleibt als Fachlogik getrennt.
Der Event-Handler bildet die Vermittlungsschicht zwischen Oberfläche und Fachlogik: Er liest Zustände aus Komponenten, ruft eine passende Verarbeitungsmethode auf und schreibt das Ergebnis in die Oberfläche zurück.
2. Zentrales Denkmodell: linearer Ablauf und GUI-Ablauf
Das klassische EVA-Modell bleibt erhalten, aber der Programmablauf wird im GUI-Kontext durch Ereignisse gesteuert.
Konsolenprogramm (linear)
Der Ablauf folgt einer festen Reihenfolge von oben nach unten.
GUI-Programm (ereignisgesteuert)
wartet auf Ereignisse
reagiert wiederholt im passenden Event-Handler
| EVA-Schritt | GUI-Umsetzung |
|---|---|
| Eingabe | Zustände aus Komponenten lesen, z. B. getText() oder isSelected() |
| Verarbeitung | Fachlogik ausführen, Bedingungen prüfen, Methoden aufrufen |
| Ausgabe | Komponenten aktualisieren, z. B. setText(...) |
Wichtig: Ein ist keine direkte Dateneingabe. Er ist ein Auslöser, der ein Ereignis erzeugt und damit die Verarbeitung startet.
Damit eine GUI auf Ereignisse reagieren kann, müssen ihre Komponenten dauerhaft verfügbar sein. Deshalb werden wichtige Komponenten häufig als Attribute der Klasse gespeichert.
3. Hauptfenster, Container und Komponenten
Ein JFrame ist das Hauptfenster einer Swing-Anwendung.
Komponenten werden darin nicht frei schwebend platziert, sondern in eine Container-Struktur eingefügt.
Ein Container kann weitere Komponenten enthalten und strukturieren.
Das Fenster ist der oberste Container; ein JPanel kann als innerer Container Komponenten gruppieren.
Sichtbare Komponenten sind z. B. JLabel, JTextField, JButton oder JCheckBox.
Typisch ist die Reihenfolge: Objekt erzeugen → konfigurieren → anordnen/positionieren → hinzufügen → später auswerten oder verändern.
Informatikfachlich bedeutet das: Fenster, Panels, Buttons und Textfelder sind Objekte mit Eigenschaften, Methoden und internem Zustand. Container strukturieren diese Objekte und erzeugen gemeinsam eine hierarchische Objektstruktur der Oberfläche.
import javax.swing.*;
public class ContainerStrukturDemo {
public static void main(String[] args) {
JFrame fenster = new JFrame("Container-Struktur");
fenster.setSize(360, 220);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenster.setLayout(null);
JPanel panel = new JPanel();
panel.setLayout(null);
panel.setBounds(20, 20, 300, 120);
JLabel beschriftung = new JLabel("Panel als innerer Container");
beschriftung.setBounds(20, 20, 220, 25);
panel.add(beschriftung);
JButton button = new JButton("Aktion");
button.setBounds(20, 60, 100, 25);
panel.add(button);
fenster.add(panel);
fenster.setVisible(true);
}
}
JFrameist das Hauptfenster.JPanelist ein innerer Container.JLabelundJButtonwerden dem Panel hinzugefügt.- Das Panel wird anschließend dem Fenster hinzugefügt.
- Dadurch entsteht eine hierarchische Struktur aus Containern und Komponenten.
4. Bausteine einer einfachen Swing-GUI
Swing-Komponenten folgen einem gemeinsamen Muster:
Der Konstruktor erzeugt ein Objekt, setBounds(...) beziehungsweise ein Layout-Manager bestimmt die Darstellung,
und mit add(...) wird die Komponente in einen Container eingefügt.
Benötigte Importpakete für die Swing-Beispiele
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
JFrame – Fenster erzeugen
JFrame fenster = new JFrame("Login");
JLabel – Text ausgeben
JLabel lblInfo = new JLabel("Bitte anmelden");
JTextField – Eingabe aufnehmen
JTextField txtUser = new JTextField();
JButton – Ereignis auslösen
JButton btnLogin = new JButton("Anmelden");
setLayout(null) – absolute Positionierung aktivieren
fenster.setLayout(null);
setBounds(...) – Position und Größe festlegen
btnLogin.setBounds(80, 90, 120, 25);
add(...) – Komponente einfügen
fenster.add(btnLogin);
setVisible(true) – Fenster anzeigen
fenster.setVisible(true);
Die Codeboxen sind bewusst isoliert dargestellt.
In einem vollständigen Programm müssen diese Bausteine in sinnvoller Reihenfolge zusammengesetzt werden.
Für die Einführungsphase wird zunächst mit setLayout(null) und setBounds(...) gearbeitet,
weil dadurch der Zusammenhang zwischen Objekt, Position und Anzeige besonders sichtbar bleibt.
Warum Komponenten oft Attribute sind
Eine lokale Variable ist außerhalb ihres Blocks beziehungsweise ihrer Methode nicht zugreifbar. Wichtige GUI-Komponenten werden deshalb oft als Attribute, also als Felder der Klasse, gespeichert: Der Konstruktor erzeugt und ordnet sie, der Listener liest oder verändert später dieselben Komponenten.
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
1. Attribute deklarieren
private JTextField txtName;
private JLabel lblAusgabe;
2. Im Konstruktor erzeugen
public MeineGUI() {
txtName = new JTextField(20);
lblAusgabe = new JLabel("Noch keine Eingabe.");
}
3. Im Listener verwenden
public void actionPerformed(ActionEvent e) {
String name = txtName.getText();
lblAusgabe.setText("Hallo, " + name + "!");
}
Wenn Komponenten dauerhaft verfügbar sind, kann der Event-Handler mit ihnen arbeiten: Er liest Zustände aus, verarbeitet Werte und schreibt Ergebnisse zurück.
5. Zustände von GUI-Komponenten lesen und verändern
- GUI-Komponenten sind Objekte mit internem Zustand.
get- undis-Methoden lesen Zustände.set-Methoden verändern Zustände.- Die Komponente bleibt bestehen; nur ihr Zustand ändert sich.
setText("")löscht nicht das Objekt, sondern setzt den Textzustand auf die leere Zeichenkette.
Beispiele: Zustände lesen und verändern
Zustände lesen
| Komponente | Code |
|---|---|
JTextField |
String text = feld.getText(); |
JLabel |
String info = label.getText(); |
JCheckBox |
boolean aktiv = check.isSelected(); |
JRadioButton |
boolean gewaehlt = radio.isSelected(); |
JComboBoxAusblick |
int index = combo.getSelectedIndex(); |
JSpinnerAusblick |
int wert = (int) spinner.getValue(); |
Zustände verändern
| Komponente | Code |
|---|---|
JLabel |
label.setText("Fertig"); |
JTextField |
feld.setText(""); |
JCheckBox |
check.setSelected(true); |
JRadioButton |
radio.setSelected(true); |
JComboBoxAusblick |
combo.setSelectedIndex(2); |
JSpinnerAusblick |
spinner.setValue(5); |
6. Vertiefung: Spezielle Layout-Formen
Vertiefung: Spezielle Layout-Formen
Bisher wurde in E3 bewusst mit setLayout(null) und setBounds(...) gearbeitet,
damit Positionen und Größen explizit sichtbar werden.
In größeren Swing-Programmen werden stattdessen Layout-Manager eingesetzt.
Sie ordnen Komponenten automatisch an und reagieren auf Fenstergrößen sowie die verfügbare Containerfläche.
In dieser Vertiefung werden drei zentrale Layouts aus der Swing-Grundausbildung betrachtet:
FlowLayout, BorderLayout und GridLayout.
Als kurzer Ausblick gelten außerdem BoxLayout, CardLayout und GridBagLayout,
die hier nicht weiter vertieft werden.
FlowLayout – zeilenweise Anordnung
Komponenten werden zeilenweise von links nach rechts angeordnet. Wenn kein Platz mehr vorhanden ist, beginnt automatisch eine neue Zeile. Die sichtbare Anordnung hängt daher direkt von der Fensterbreite ab.
Hinweis: Das Beispiel nutzt hier extends JFrame, weil viele Swing-Quellen so kompakt erklären. Die bisherigen E3-Beispiele arbeiten weiterhin ohne Vererbung über ein separates JFrame-Objekt.
import javax.swing.*;
import java.awt.FlowLayout;
public class FlowLayoutDemo extends JFrame {
public FlowLayoutDemo() {
setTitle("FlowLayoutDemo");
setSize(500, 160);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout(FlowLayout.LEFT));
add(new JButton("Button 1"));
add(new JButton("Button 2"));
add(new JButton("Button 3"));
add(new JButton("Long-Named Button 4"));
add(new JButton("5"));
setVisible(true);
}
public static void main(String[] args) {
new FlowLayoutDemo();
}
}
BorderLayout – fünf Bereiche
Die Containerfläche wird in fünf Bereiche eingeteilt: NORTH, WEST, SOUTH, EAST und CENTER. Bei Größenänderungen wächst besonders der CENTER-Bereich; die Randbereiche passen sich entsprechend an. Direkt pro Position kann höchstens eine Komponente eingefügt werden (für mehrere Elemente nutzt man z. B. ein zusätzliches JPanel).
import javax.swing.*;
import java.awt.BorderLayout;
public class BorderLayoutDemo extends JFrame {
public BorderLayoutDemo() {
setTitle("BorderLayoutDemo");
setSize(420, 240);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(new JButton("North"), BorderLayout.NORTH);
add(new JButton("West"), BorderLayout.WEST);
add(new JButton("South"), BorderLayout.SOUTH);
add(new JButton("East"), BorderLayout.EAST);
add(new JButton("Center"), BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
new BorderLayoutDemo();
}
}
GridLayout – gitterförmige Anordnung
Komponenten werden gitterförmig angeordnet. Jede Komponente ist gleich groß und nutzt den verfügbaren Platz vollständig aus. new GridLayout(0, 2) bedeutet dabei: beliebig viele Zeilen und genau zwei Spalten.
import javax.swing.*;
import java.awt.GridLayout;
public class GridLayoutDemo extends JFrame {
public GridLayoutDemo() {
setTitle("GridLayoutDemo");
setSize(420, 220);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(0, 2));
add(new JButton("Button 1"));
add(new JButton("Button 2"));
add(new JButton("Button 3"));
add(new JButton("Long-Named Button 4"));
add(new JButton("5"));
setVisible(true);
}
public static void main(String[] args) {
new GridLayoutDemo();
}
}
7. Vertiefung: Weitere Swing-Komponenten
Vertiefung: Weitere Swing-Komponenten
Swing stellt viele weitere GUI-Komponenten bereit. In E3 werden davon nur ausgewählte Komponenten betrachtet. Die folgenden Beispiele sind optional und zeigen typische Eingabe-, Auswahl- und Strukturierungselemente. Alle Komponenten folgen demselben Grundprinzip: Objekt erzeugen, konfigurieren, positionieren, hinzufügen und bei Bedarf im Event-Handler auswerten.
import javax.swing.*;
JCheckBox – unabhängige Auswahl
Eine JCheckBox eignet sich für Optionen, die unabhängig voneinander ein- oder ausgeschaltet werden können. Die Eingabe wird als Wahrheitswert modelliert und mit isSelected() ausgewertet. Im EVA-Sinn liefert sie Eingabezustände, die in der Verarbeitung geprüft werden.
JCheckBox newsletter = new JCheckBox("Newsletter abonnieren");
newsletter.setBounds(20, 20, 220, 25);
fenster.add(newsletter);
boolean ausgewaehlt = newsletter.isSelected();
JRadioButton + ButtonGroup – genau eine Auswahl
JRadioButton wird verwendet, wenn aus mehreren Alternativen genau eine gewählt werden soll. Eine ButtonGroup organisiert die gegenseitige Ausschließlichkeit der Auswahl. Für EVA bedeutet das: klare Eingabeoptionen, deren Zustand im Event-Handler abgefragt werden kann.
JRadioButton klein = new JRadioButton("klein");
klein.setBounds(20, 20, 100, 25);
JRadioButton gross = new JRadioButton("groß");
gross.setBounds(20, 50, 100, 25);
ButtonGroup gruppe = new ButtonGroup();
gruppe.add(klein);
gruppe.add(gross);
fenster.add(klein);
fenster.add(gross);
if (gross.isSelected()) {
ausgabe.setText("Groß wurde gewählt.");
}
JComboBox – Auswahl aus einer Liste
Eine JComboBox bietet eine kompakte Auswahl aus mehreren vorgegebenen Werten. Typisch ist die Auswertung mit getSelectedItem(). Dadurch werden freie Texteingaben reduziert und mögliche Eingabefehler im Eingabeschritt minimiert.
String[] farben = {"Rot", "Grün", "Blau"};
JComboBox<String> auswahl = new JComboBox<>(farben);
auswahl.setBounds(20, 20, 120, 25);
fenster.add(auswahl);
String farbe = (String) auswahl.getSelectedItem();
JTextArea – mehrzeilige Texteingabe
Eine JTextArea erlaubt längere oder mehrzeilige Eingaben. Mit getText() wird der gesamte Textinhalt ausgelesen. In EVA kann so umfangreichere Eingabe gesammelt und danach verarbeitet werden.
JTextArea textbereich = new JTextArea();
textbereich.setBounds(20, 20, 220, 80);
fenster.add(textbereich);
String text = textbereich.getText();
JPasswordField – verdeckte Texteingabe
Ein JPasswordField ist für verdeckte Eingaben gedacht. Die Zeichen werden nicht offen angezeigt; zur Auswertung dient typischerweise getPassword(), das ein char[] liefert. Hier wird dies didaktisch vereinfacht in einen String umgewandelt.
JPasswordField passwortFeld = new JPasswordField();
passwortFeld.setBounds(20, 20, 160, 25);
fenster.add(passwortFeld);
String passwort = new String(passwortFeld.getPassword());
JPanel – Komponenten gruppieren
Ein JPanel kann Komponenten gruppieren und später auch eigene Layouts enthalten. Es ist damit ein Strukturierungselement innerhalb des Hauptfensters und verdeutlicht das Container-Prinzip. In EVA unterstützt es vor allem den geordneten Aufbau der Eingabe- und Ausgabeelemente.
JPanel panel = new JPanel();
panel.setLayout(null);
panel.setBounds(10, 10, 250, 100);
JLabel label = new JLabel("Gruppe");
label.setBounds(20, 20, 100, 25);
panel.add(label);
fenster.add(panel);
Weitere Komponenten wie JList, JMenuBar, JOptionPane oder JSlider sind möglich, werden hier aber nur als Ausblick betrachtet. Entscheidend ist das Grundprinzip: passende Komponente auswählen, als Objekt erzeugen, konfigurieren, hinzufügen und über Methoden bzw. Ereignisse nutzen.
Zustände allein machen eine GUI noch nicht interaktiv. Erst durch Ereignisse wird festgelegt, wann diese Zustände gelesen oder verändert werden.
8. ActionListener und ActionEvent
Ereignisverarbeitung trennt den Aufbau der Oberfläche vom Verhalten des Programms.
Der GUI-Aufbau beschreibt, welche Objekte sichtbar sind; der Listener beschreibt, wie auf ein Ereignis reagiert wird.
Ein Ereignis ist z. B. ein Button-Klick oder eine Auswahländerung.
Über addActionListener(...) wird eine Reaktion registriert.
Die Methode actionPerformed(...) wird erst ausgeführt, wenn das Ereignis eintritt.
Ein Button ist damit Auslöser, nicht Datenspeicher und nicht die Verarbeitung selbst. Welche Verarbeitungsroutine beim Klick ausgeführt wird, steht im registrierten Listener.
Ereignisquelle → Ereignisobjekt → Listener → actionPerformed(...) → Reaktion
Button-Klick
↓
ActionEvent entsteht
↓
registrierter Listener reagiert
↓
actionPerformed(...) wird ausgeführt
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
Listener registrieren
button.addActionListener(this);
Reaktion formulieren
public void actionPerformed(ActionEvent e) {
label.setText("Geklickt");
}
Die Schreibweise this ist nur dann möglich, wenn das aktuelle Objekt selbst als Listener verwendet wird.
Die Grundidee bleibt in beiden Schreibweisen gleich: Eine Reaktion wird registriert und später beim Ereignis ausgeführt.
btnLogin.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Dieser Block wird erst beim Klick auf den Button ausgeführt.
}
});
ActionEvent e ist ein Ereignisobjekt mit Informationen über das ausgelöste Ereignis,
zum Beispiel welche Komponente die Aktion ausgelöst hat.
Für den Einstieg ist vor allem wichtig:
Der Code in actionPerformed(...) läuft nicht beim Programmstart, sondern erst dann,
wenn der Button angeklickt wird.
Object quelle = e.getSource();
Diese Information muss in einfachen Programmen nicht immer ausgewertet werden.
Sie erklärt aber, warum actionPerformed(...) ein Ereignisobjekt als Parameter erhält.
Auch die in der Vertiefung gezeigten Komponenten können im Event-Handler ausgewertet werden,
zum Beispiel mit isSelected(), getSelectedItem() oder getText().
Im Event-Handler werden Eingabezustände gelesen und Reaktionen koordiniert.
Dort lassen sich bekannte Kontrollstrukturen wie if, else, Schleifen oder Methodenaufrufe verwenden.
Die Fachlogik sollte aber nicht vollständig im Listener verschwinden:
Ein Button-Klick kann eine Methode auslösen, die Berechnung oder Prüfung selbst bleibt als Verarbeitungsroutine benannt.
Damit werden die Inhalte aus den vorherigen Kapiteln zu Methoden und Kontrollstrukturen direkt in den GUI-Kontext übertragen.
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = eingabe.getText();
if (name.equals("")) {
ausgabe.setText("Bitte Namen eingeben.");
} else {
ausgabe.setText("Hallo, " + name + "!");
}
}
});
getText()liest die Eingabe aus dem Textfeld.ifprüft eine Bedingung und unterscheidet zwischen leerer und nicht leerer Eingabe.setText(...)setzt abhängig vom Ergebnis unterschiedliche Ausgaben.- Die Kontrollstruktur steht innerhalb von
actionPerformed(...), weil sie erst beim Button-Klick ausgeführt werden soll.
9. Vom GUI-Aufbau zum Ereignisablauf: EVA mit Event-Handling
GUI-Programme bestehen aus Aufbau und Verhalten. Zum Aufbau gehören Fenster, Komponenten, Positionen und Container. Zum Verhalten gehören die Reaktion auf Ereignisse, das Lesen von Eingaben, die Verarbeitung und die Ausgabe. Der Event-Handler verbindet beides: Er arbeitet mit den sichtbaren Objekten, sobald ein Benutzerereignis eintritt.
Das folgende Minimalbeispiel kombiniert die vorherigen Bausteine vollständig und zeigt den Weg von Eingabe über Ereignis und Verarbeitung zur Ausgabe.
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GuiEvaMinimal {
public static void main(String[] args) {
JFrame fenster = new JFrame("Anhalteweg");
fenster.setSize(320, 160);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenster.setLayout(null);
JTextField eingabe = new JTextField();
eingabe.setBounds(20, 20, 160, 25);
fenster.add(eingabe);
JButton button = new JButton("Berechnen");
button.setBounds(190, 20, 100, 25);
fenster.add(button);
JLabel ausgabe = new JLabel("Noch keine Berechnung.");
ausgabe.setBounds(20, 70, 260, 25);
fenster.add(ausgabe);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double v = Double.parseDouble(eingabe.getText());
double weg = berechneAnhalteweg(v);
ausgabe.setText("Anhalteweg: " + weg);
}
});
fenster.setVisible(true);
}
public static double berechneAnhalteweg(double v) {
return v * v / 100.0;
}
}
- Aufbau:
JFrame,JTextField,JButtonundJLabelwerden erzeugt und hinzugefügt. - Ereignis: Ein Button-Klick startet
actionPerformed(...). - Eingabe:
getText()liest Text aus dem Textfeld,Double.parseDouble(...)macht daraus eine Zahl. - Verarbeitung:
berechneAnhalteweg(...)kapselt die Berechnung. - Ausgabe:
setText(...)aktualisiert das Label. - Trennung: Dieselbe Methode könnte auch aus einem Konsolenprogramm oder Test heraus aufgerufen werden.
Startzustand und Ereignis anzeigen
Startzustand
- Textfeld enthält
"50". - Label zeigt
"Noch keine Berechnung.". - Button wartet auf einen Klick.
Ereignis
Der Benutzer klickt Berechnen. Dadurch startet der registrierte Event-Handler.
Event-Trace anzeigen
| Schritt | Anweisung / Aktion | Wirkung |
|---|---|---|
| 1 | actionPerformed(...) | Der Event-Handler startet. |
| 2 | eingabe.getText() | Liefert "50". |
| 3 | Double.parseDouble("50") | Liefert 50.0. |
| 4 | berechneAnhalteweg(50.0) | Liefert 25.0. |
| 5 | ausgabe.setText(...) | Setzt den Labeltext. |
Endzustand anzeigen
Textfeld
Bleibt "50".
Label
Zeigt "Anhalteweg: 25.0".
Deutung: Der Button berechnet nicht selbst. Er löst ein Ereignis aus. Der Event-Handler liest den Zustand des Textfelds, ruft die Fachlogik auf und schreibt das Ergebnis zurück in das Label.
Benutzeraktion → GUI-Komponente → Event-Handler → Verarbeitung → GUI-Ausgabe
Die GUI ist die Schnittstelle zwischen Benutzer und Programm. Der Event-Handler ist die Schnittstelle zwischen Oberfläche und Fachlogik: Er liest Zustände aus Komponenten, ruft Verarbeitung auf und schreibt Ergebnisse zurück.
Für größere Programme gilt: Die Oberfläche steuert Ein- und Ausgabe. Berechnungen und Prüfungen sollten möglichst in getrennten Methoden liegen, damit der Event-Handler als Vermittlungsschicht übersichtlich bleibt. Das betrifft zum Beispiel Gehalt, Bremsweg oder Prüfregeln.
Typische Fehlvorstellungen beim Event-Handling
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
Ein Button ist Auslöser, nicht Datenspeicher. Die eigentlichen Daten stehen z. B. in Textfeldern, Labels oder Variablen.
// Der Button löst nur aus.
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = eingabe.getText();
ausgabe.setText("Hallo, " + name + "!");
}
});
Der Code in actionPerformed(...) wird erst ausgeführt, wenn das registrierte Ereignis eintritt.
System.out.println("Programmstart");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button wurde geklickt");
}
});
setText(...) verändert nur den Textzustand der Komponente.
double summe = a + b; // Fachlogik
ausgabe.setText("Summe: " + summe); // GUI-Ausgabe
Ein Klick startet nicht main(...) neu.
public static void main(String[] args) {
// Wird beim Programmstart ausgeführt.
}
public void actionPerformed(ActionEvent e) {
// Wird beim Klick ausgeführt.
}
Bei größeren Programmen sollte Fachlogik ausgelagert werden.
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double geschwindigkeit =
Double.parseDouble(eingabe.getText());
double anhalteweg =
berechneAnhalteweg(geschwindigkeit);
ausgabe.setText(
"Anhalteweg: " + anhalteweg
);
}
});
public static double berechneAnhalteweg(double v) {
return v * v / 100.0;
}
10. Weitere Beispiele zur Vertiefung
Die folgenden größeren Anwendungsbeispiele vertiefen dieselbe Leitidee: sichtbare Eingabe und Ausgabe, Auslösung durch Benutzerereignisse und Verarbeitung in passenden Methoden.
Variantenbeispiel: Begrüßung mit Texteingabe
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = eingabe.getText().trim();
if (name.equals("")) {
name = "Gast";
}
ausgabe.setText("Hallo, " + name + "!");
}
});
Weiteres Beispiel: Addition zweier Zahlen
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GuiAddition {
public static void main(String[] args) {
JFrame fenster = new JFrame("Addition");
fenster.setSize(360, 180);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenster.setLayout(null);
JTextField eingabeA = new JTextField();
eingabeA.setBounds(20, 20, 80, 25);
fenster.add(eingabeA);
JTextField eingabeB = new JTextField();
eingabeB.setBounds(110, 20, 80, 25);
fenster.add(eingabeB);
JButton button = new JButton("Addieren");
button.setBounds(200, 20, 110, 25);
fenster.add(button);
JLabel ausgabe = new JLabel("Noch kein Ergebnis.");
ausgabe.setBounds(20, 70, 280, 25);
fenster.add(ausgabe);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double a = Double.parseDouble(eingabeA.getText());
double b = Double.parseDouble(eingabeB.getText());
double summe = a + b;
ausgabe.setText("Summe: " + summe);
}
});
fenster.setVisible(true);
}
}
11. Weiterführende Dokumentation
Die hier behandelten Inhalte sind eine didaktische Auswahl.
Insbesondere Hauptfenster/Container, Swing-Komponenten, Layout-Manager und Ereignisverarbeitung wurden fachlich reduziert übernommen.
Swing umfasst deutlich mehr Themen wie Dialogfenster, Zeichnen mit paintComponent, GUI-Builder, Threads oder MVC;
diese werden hier nur als Ausblick genannt.
Die fachliche Struktur orientiert sich unter anderem an der Vorlesungsunterlage
Grafische Benutzeroberflächen mit Swing
von O. Bittel, HTWG Konstanz.
Weitere Details finden sich in der offiziellen Java-Dokumentation:
Diese Bausteine führen zum Abschlussgedanken: Aus strukturierten Abläufen und Methoden entstehen benannte Verarbeitungsroutinen, an die Q1.2 und Q1.3 fachlich anschließen.
Von Methoden zu algorithmischen Routinen
Programmierte Verarbeitung als Vorform algorithmischen Denkens
Programmierte Verarbeitung als Vorform algorithmischen Denkens
E3 entwickelt noch keine formale Algorithmusanalyse. Die Seite bereitet den Algorithmus-Begriff vor, indem Verarbeitung klar strukturiert wird: Anweisungen werden durch Kontrollstrukturen geordnet, wiederkehrende Folgen werden in Methoden gekapselt, und EVA macht Eingabe, Verarbeitung und Ausgabe als zusammenhängendes Funktionsmodell lesbar.
Eine Methode kann in diesem Sinn als benannte Verarbeitungsroutine gelesen werden. Sie besitzt Eingaben, Verarbeitungsschritte, Kontrollstrukturen und ein Ergebnis. In GUI-Systemen wird dieselbe Routine ereignisgesteuert ausgelöst: Benutzeraktion → Eingabezustand lesen → Verarbeitung ausführen → Ausgabe aktualisieren. Die systematische Untersuchung als Verfahren folgt in Q1.2.
| Bereich | Leitfrage |
|---|---|
| E3 | Wie strukturiere ich Verarbeitung in einem Programm? |
| Q1.2 | Welche Such- oder Sortierstrategie löst ein Problem effizient? |
| Q1.3 | Kann ich ein Problem durch kleinere Probleme derselben Art beschreiben? |
Die konkrete Ausarbeitung von Such- und Sortieralgorithmen gehört deshalb nach Q1.2: Dort werden Voraussetzungen, Darstellungen, Korrektheit, Laufzeit und Effizienz systematisch verglichen. Q1.3 verschiebt anschließend den Blick auf rekursive Problemstruktur, Teilprobleme, Basisfall und Rekursionsschritt.
E5-Ausblick im Java-Werkzeug
Diese Aufgaben nutzen E3-Bausteine wie Schleifen, Strings, Arrays, char-Rechnung und Modulo in kryptologischen Verfahren. Die fachliche Kryptologie wird in E5 vertieft.
Diagnoseperspektive: Programmieren als prüfende Praxis
Programmieren bedeutet in E3 nicht nur, Code zu schreiben. Entscheidend ist, die Wirkung einer Anweisung, eines Ausdrucks oder einer Methode prüfen zu können. Fehler werden deshalb nach ihrer Entstehungsstelle gelesen.
| Fehlerart | Beispiel | Diagnosefrage |
|---|---|---|
| Syntaxfehler | Semikolon fehlt | Meldet der Compiler einen Fehler? |
| Laufzeitfehler | ungültiger Arrayindex | Welche Werte liegen beim Zugriff vor? |
| Logikfehler | falsche Bedingung | Wird der Ausdruck richtig ausgewertet? |
| Eingabefehler | Text statt Zahl | Wird die Eingabe geprüft oder umgewandelt? |
| GUI-Fehler | Button tut nichts | Ist ein Listener registriert? |
| Methodenfehler | Rückgabewert wird nicht gespeichert | Wird return an der Aufrufstelle genutzt? |