diff --git a/docs/additional-material/instructions/binary-numbers.mdx b/docs/additional-material/instructions/binary-numbers.mdx
index 78626717bb..f278071789 100644
--- a/docs/additional-material/instructions/binary-numbers.mdx
+++ b/docs/additional-material/instructions/binary-numbers.mdx
@@ -10,8 +10,8 @@ import TabItem from '@theme/TabItem';
## Binärzahlen in Dezimalzahlen umwandeln
-Zur Umwandlung einer Binärzahl in eine Dezimalzahl muss das Produkt aus
-Stellenwert und Ziffer jeder Stelle aufsummiert werden.
+Um eine Binärzahl in eine Dezimalzahl umzuwandeln, wird das Produkt aus
+Stellenwert und Ziffer jeder Stelle aufsummiert.
| Potenz | Stellenwert | Ziffer | Stellenwert \* Ziffer |
| -------------- | ----------- | ------ | --------------------- |
@@ -30,8 +30,8 @@ Stellenwert und Ziffer jeder Stelle aufsummiert werden.
## Natürliche Dezimalzahlen in Binärzahlen umwandeln
-Zur Umwandlung einer natürlichen Dezimalzahl in eine Binärzahl kann entweder
-eine Stellenwerttabelle oder das Divisions-Verfahren verwendet werden.
+Eine natürliche Dezimalzahl lässt sich entweder mit einer Stellenwerttabelle
+oder dem Divisions-Verfahren in eine Binärzahl umwandeln.
Im Beispiel soll die Zahl 52510 in eine Binärzahl umgewandelt werden.
@@ -76,10 +76,9 @@ Im Beispiel soll die Zahl 52510 in eine Binärzahl umgewandelt werden
## Bilden des Zweierkomplements
-Zum Bilden des Zweierkomplements wird zunächst das Einerkomplement gebildet,
-d.h. alle Bits werden invertiert. Hierbei ist zu beachten, dass einer positiven
-Binärzahl unendlich viele Nullen vorangestellt sind. Anschließend wird noch eine
-1 hinzuaddiert.
+Das Zweierkomplement entsteht, indem zunächst das Einerkomplement gebildet wird
+(alle Bits werden invertiert) und anschließend eine 1 hinzuaddiert wird. Einer
+positiven Binärzahl sind dabei unendlich viele Nullen vorangestellt.
Im Beispiel soll die Zahl -9510 im Zweierkomplement dargestellt
werden.
@@ -90,7 +89,7 @@ werden.
| Invertieren | 1 | ... | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
| 1 Addieren | 1 | ... | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 |
-:::info
+:::note
Die Rückumwandlung erfolgt analog.
@@ -98,8 +97,8 @@ Die Rückumwandlung erfolgt analog.
## Reelle Dezimalzahlen in Binärzahlen umwandeln
-Zur Umwandlung einer reellen Dezimalzahl in eine Binärzahl kann entweder eine
-Stellenwerttabelle oder das Multiplikations-Verfahren verwendet werden.
+Eine reelle Dezimalzahl lässt sich entweder mit einer Stellenwerttabelle oder
+dem Multiplikations-Verfahren in eine Binärzahl umwandeln.
Im Beispiel soll die Zahl 0,110 in eine Binärzahl umgewandelt werden.
@@ -138,12 +137,12 @@ Im Beispiel soll die Zahl 0,110 in eine Binärzahl umgewandelt werden
## Reelle Dezimalzahlen in Gleitkommazahlen umwandeln
-Bei der Umwandlung einer reellen Zahl in eine Gleitkommazahl werden zunächst
-Vor- und Nachkommazahl in Binärzahlen umgewandelt. Anschließend wird durch
-Gleiten bzw. Verschieben des Kommas zur führenden 1, dem Runden auf das LSB
-sowie dem Entfernen der führenden 1 die Mantisse ermittelt. Nach dem Ermitteln
-der Mantisse wird zum Exponenten noch der Bias (127 bei einfacher Genauigkeit,
-1023 bei doppelter Genauigkeit) hinzuaddiert sowie das Vorzeichen umgewandelt.
+Bei der Umwandlung einer reellen Zahl in eine Gleitkommazahl werden Vor- und
+Nachkommazahl zunächst in Binärzahlen umgewandelt. Durch Verschieben des Kommas
+zur führenden 1, Runden auf das LSB und Entfernen der führenden 1 entsteht die
+Mantisse. Zum Exponenten wird anschließend der Bias addiert (127 bei einfacher,
+1023 bei doppelter Genauigkeit), und das Vorzeichen wird als einzelnes Bit
+gespeichert.
Im Beispiel soll die Zahl -27,0410 in eine Gleitkommazahl mit
einfacher Genauigkeit umgewandelt werden.
@@ -163,16 +162,14 @@ einfacher Genauigkeit umgewandelt werden.
## Binärzahlen addieren und subtrahieren
-Für die Addition von Binärzahlen gelten folgende Regeln:
+Für die Addition von Binärzahlen gelten vier Regeln. Die Subtraktion erfolgt
+durch Addition des Zweierkomplements: `a - b = a + (-b)`.
- Fall 1: `0 + 0 = 0`
- Fall 2: `0 + 1 = 1`
- Fall 3: `1 + 0 = 1`
- Fall 4: `1 + 1 = 0 (Übertrag 1)`
-Die Subtraktion von Binärzahlen erfolgt durch die Addition des
-Zweierkomplements. Es gilt: `a - b = a + (-b)`.
-
@@ -228,9 +225,9 @@ Im Beispiel werden die Zahlen -3 und -47 addiert.
-:::info
+:::note
-Der bei der Addition des Zweierkomplements auftretende mögliche Stellenüberlauf
-wird ignoriert.
+Der bei der Addition des Zweierkomplements möglicherweise auftretende
+Stellenüberlauf wird ignoriert.
:::
diff --git a/docs/additional-material/instructions/debugging.md b/docs/additional-material/instructions/debugging.md
new file mode 100644
index 0000000000..ca0e5ad4bc
--- /dev/null
+++ b/docs/additional-material/instructions/debugging.md
@@ -0,0 +1,128 @@
+---
+title: Debuggen mit Eclipse
+description: ''
+sidebar_position: 50
+tags: [debugging, eclipse]
+---
+
+:::tip
+
+Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/) und
+[Eclipse](https://www.eclipse.org/)
+
+:::
+
+Der in Eclipse integrierte Debugger ermöglicht es, ein Java-Programm
+kontrolliert auszuführen, an beliebigen Stellen anzuhalten und den Zustand von
+Variablen sowie den Programmfluss zu inspizieren. Die folgenden Abschnitte
+führen schrittweise durch die wichtigsten Debugging-Funktionen in Eclipse.
+
+## Programm im Debug-Modus starten
+
+Um den Debugger zu nutzen, muss das Programm explizit im Debug-Modus gestartet
+werden. Ohne diesen Modus sind Breakpoints und Schrittausführung nicht
+verfügbar.
+
+- Öffne das gewünschte Java-Projekt in Eclipse
+- Navigiere im _Package Explorer_ zur Startklasse (der Klasse mit der
+ `main`-Methode)
+- Öffne das Kontextmenü der Startklasse (Rechtsklick) und führe **Debug As →
+ Java Application** aus
+
+:::tip
+
+Das Programm kann alternativ über die Werkzeugleiste mit der Schaltfläche
+**Debug** (Käfer-Symbol) oder mit dem Tastaturkürzel `F11` im Debug-Modus
+gestartet werden.
+
+:::
+
+## Breakpoint setzen
+
+Ein Breakpoint markiert eine Zeile, an der die Programmausführung pausieren
+soll. Eclipse hält an dieser Stelle an, bevor die markierte Zeile ausgeführt
+wird.
+
+- Navigiere im Editor zur gewünschten Zeile
+- Führe im grauen Randbereich links der Zeilennummer (Rechtsklick) die Funktion
+ **Toggle Breakpoint** aus
+
+Ein blauer Kreis im Randbereich zeigt an, dass der Breakpoint aktiv ist.
+
+:::tip
+
+Ein Breakpoint kann auch durch einen Doppelklick auf den grauen Randbereich
+links der Zeilennummer gesetzt bzw. entfernt werden.
+
+:::
+
+## Debug-Perspektive verwenden
+
+Sobald das Programm an einem Breakpoint anhält, wechselt Eclipse automatisch in
+die _Debug-Perspektive_. Sie besteht aus mehreren spezialisierten Ansichten, die
+gemeinsam ein vollständiges Bild des aktuellen Programmzustands liefern.
+
+- **Debug**: zeigt den Call Stack (Aufrufhierarchie der aktiven Methoden)
+- **Variables**: zeigt alle aktuell sichtbaren Variablen und deren Werte
+- **Breakpoints**: listet alle gesetzten Breakpoints und erlaubt das
+ Aktivieren/Deaktivieren einzelner Breakpoints
+- **Console**: zeigt die Standardausgabe des laufenden Programms
+- **Expressions**: wertet beliebige Java-Ausdrücke im aktuellen Kontext aus
+ (z.B. `list.size()` oder `obj.getName()`)
+
+## Programm schrittweise ausführen
+
+Sobald das Programm an einem Breakpoint pausiert, stehen verschiedene
+Schritt-Befehle zur Verfügung, um die Ausführung gezielt fortzusetzen und den
+Kontrollfluss zu verfolgen.
+
+- Führe **Run → Step Over** (`F6`) aus, um die aktuelle Zeile vollständig
+ auszuführen und in der nächsten Zeile derselben Methode anzuhalten
+- Führe **Run → Step Into** (`F5`) aus, um in den Rumpf des aufgerufenen
+ Methodenaufrufs hineinzuspringen
+- Führe **Run → Step Return** (`F7`) aus, um die aktuelle Methode vollständig
+ auszuführen und zur aufrufenden Stelle zurückzukehren
+- Führe **Run → Resume** (`F8`) aus, um die Ausführung bis zum nächsten
+ Breakpoint fortzusetzen
+
+## Variablenwerte inspizieren
+
+Die View _Variables_ zeigt den aktuellen Zustand aller sichtbaren Variablen.
+Objekte können aufgeklappt werden, um ihre Felder zu inspizieren.
+
+- Navigiere in der Debug-Perspektive zur View _Variables_
+- Klappe Objekte durch Betätigen des Dreiecks links des Variablennamens auf
+- Der aktuelle Wert einer Variablen wird in der Spalte **Value** angezeigt
+
+:::tip
+
+Fahre im Editor mit der Maus über einen Variablennamen, um dessen aktuellen Wert
+als Tooltip anzuzeigen. Für komplexere Ausdrücke steht die View _Expressions_
+zur Verfügung: Rechtsklick im Editor → **Watch**.
+
+:::
+
+## Bedingten Breakpoint setzen
+
+Ein bedingter Breakpoint pausiert die Ausführung nur dann, wenn eine angegebene
+boolesche Bedingung erfüllt ist. Das ist besonders nützlich, wenn ein Fehler nur
+bei bestimmten Werten auftritt – etwa ab einem bestimmten Schleifendurchlauf.
+
+- Setze zunächst einen gewöhnlichen Breakpoint (siehe oben)
+- Führe im Randbereich auf dem Breakpoint-Symbol (Rechtsklick) die Funktion
+ **Breakpoint Properties...** aus
+- Aktiviere die Option **Enable Condition**
+- Trage eine boolesche Bedingung im Textfeld ein (z.B. `i == 42`)
+- Betätige **OK**
+
+Der Breakpoint pausiert die Ausführung nun nur noch, wenn die angegebene
+Bedingung `true` ergibt.
+
+## Debug-Perspektive verlassen
+
+Nach dem Abschluss der Fehlersuche sollte die Debug-Perspektive ordentlich
+beendet und zur Java-Perspektive zurückgewechselt werden.
+
+- Führe **Run → Terminate** (`Ctrl+F2`) aus, um das laufende Programm zu beenden
+- Wechsle über den Perspektiven-Umschalter in der Werkzeugleiste (oben rechts)
+ zurück zur _Java_-Perspektive
diff --git a/docs/additional-material/instructions/git.md b/docs/additional-material/instructions/git.md
index 919ccb3dc6..2719004dc7 100644
--- a/docs/additional-material/instructions/git.md
+++ b/docs/additional-material/instructions/git.md
@@ -5,7 +5,7 @@ sidebar_position: 30
tags: [git]
---
-:::info
+:::tip
Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
[Eclipse](https://www.eclipse.org/) und [Git](https://git-scm.com/downloads)
@@ -14,6 +14,10 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## Remote Repository anlegen
+Ein Remote Repository auf GitHub dient als zentraler Ablageort für den
+Quellcode. Zusätzlich wird ein Personal Access Token benötigt, um sich von der
+Kommandozeile aus zu authentifizieren.
+
- Registriere Dich bei [GitHub](https://github.com/)
- Melde Dich bei [GitHub](https://github.com/) an
- Führe die Funktion **New** aus
@@ -32,6 +36,9 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## Git konfigurieren
+Vor der ersten Nutzung muss Git mit dem eigenen Namen und der E-Mail-Adresse
+konfiguriert werden. Diese Angaben erscheinen in jedem Commit.
+
- Starte die Kommandozeile (z.B. Windows PowerShell)
- Führe den Befehl `git config --global user.name "[Dein Name]"` aus, um den
Benutzernamen festzulegen (z.B.
@@ -42,6 +49,9 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## Lokales Repository anlegen
+Ein lokales Repository kann entweder neu initialisiert (Variante A) oder direkt
+vom Remote Repository geklont werden (Variante B).
+
**Variante A: Via Git Init**
- Starte die Kommandozeile (z.B. Windows PowerShell)
@@ -70,6 +80,8 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## Lokales Repository in Eclipse einbinden
+Nach dem Anlegen des lokalen Repositorys wird es als Eclipse-Projekt importiert.
+
- Starte Eclipse
- Führe die Funktion **File - Import... - General - Projects from Folder or
Archive** aus und betätige die Drucktaste **Next >**
@@ -79,6 +91,10 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## Remote Repository aktualisieren (bei Änderungen im lokalen Repository)
+Lokale Änderungen werden indiziert, als Commit versioniert und anschließend ins
+Remote Repository übertragen. Das ist entweder über die Kommandozeile oder
+direkt in Eclipse möglich.
+
**Variante A: Via Kommandozeile**
- Führe mehrmals den Befehl `git add [Die zu indizierende Datei]` aus, um die
@@ -104,6 +120,10 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## Lokales Repository aktualisieren (bei Änderungen im remote Repository)
+Änderungen aus dem Remote Repository werden in den lokalen Arbeitsbereich
+übertragen. Das ist entweder über die Kommandozeile oder direkt in Eclipse
+möglich.
+
**Variante A: Via Kommandozeile**
- Starte die Kommandozeile (z.B. Windows PowerShell)
diff --git a/docs/additional-material/instructions/javafx.md b/docs/additional-material/instructions/javafx.md
index f753f8747d..42e1c20f3c 100644
--- a/docs/additional-material/instructions/javafx.md
+++ b/docs/additional-material/instructions/javafx.md
@@ -5,7 +5,7 @@ sidebar_position: 40
tags: [javafx]
---
-:::info
+:::tip
Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
[Eclipse](https://www.eclipse.org/),
@@ -16,6 +16,9 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## Scene Builder mit Eclipse verbinden
+Damit Eclipse den Scene Builder öffnen kann, muss der Pfad zur ausführbaren
+Datei einmalig konfiguriert werden.
+
- Starte Eclipse
- Navigiere zu **Window – Preferences – JavaFX**
- Gib beim Feld **SceneBuilder executable** den Wert **[Der Pfad zur
@@ -24,6 +27,10 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/),
## JavaFX-Anwendung ausführen
+Eine JavaFX-Anwendung kann entweder als ausführbare JavaFX-Anwendung über das
+Maven-Plugin (Variante A) oder über eine separate Startklasse (Variante B)
+gestartet werden.
+
**Variante A: Via ausführbarer JavaFX-Anwendung**
- Starte Eclipse
@@ -97,6 +104,10 @@ public class MainClass {
## Ausführbare JavaFX-Anwendung debuggen
+Um eine ausführbare JavaFX-Anwendung im Debug-Modus zu starten, wird das
+JavaFX-Maven-Plugin um eine Debug-Konfiguration erweitert und anschließend mit
+dem Goal `javafx:run@debug` ausgeführt.
+
- Starte Eclipse
- Navigiere in der View _Package Explorer_ zu Deinem Maven-Projekt
- Navigiere in Deinem Maven-Projekt zur Datei _pom.xml_ und öffne diese
diff --git a/docs/additional-material/instructions/jdk.md b/docs/additional-material/instructions/jdk.md
index 5897a65279..a475b5c856 100644
--- a/docs/additional-material/instructions/jdk.md
+++ b/docs/additional-material/instructions/jdk.md
@@ -5,7 +5,7 @@ sidebar_position: 10
tags: [jdk]
---
-:::info
+:::tip
Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/)
@@ -13,6 +13,10 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/)
## Quellcode-Datei erstellen
+Eine Java-Quellcode-Datei enthält genau eine öffentliche Klasse, deren Name dem
+Dateinamen entsprechen muss. Die Datei liegt in einem Paketordner und trägt die
+Endung _.java_.
+
- Erstelle ein Arbeitsverzeichnis (z.B. _C:\Users\Daniel Appenmaier\Java_)
- Erstelle im eben erstellten Arbeitsverzeichnis einen Ordner (z.B. _main_)
- Erstelle im eben erstellten Ordner eine Datei mit der Endung _.java_ (z.B.
@@ -34,6 +38,9 @@ public class HelloWorld {
## Quellcode-Datei kompilieren
+Der Java-Compiler `javac` übersetzt die Quellcode-Datei in eine Bytecode-Datei
+(_.class_).
+
- Starte die Kommandozeile (z.B. Windows PowerShell)
- Führe den Befehl `cd "[Der Pfad zu Deinem Arbeitsverzeichnis]"` aus, um zum
Arbeitsbereich zu wechseln (z.B. `cd "C:\Users\Daniel Appenmaier\Java"`)
@@ -42,6 +49,8 @@ public class HelloWorld {
## Bytecode-Datei ausführen
+Die Java Virtual Machine `java` führt die kompilierte Bytecode-Datei aus.
+
- Starte die Kommandozeile (z.B. Windows PowerShell)
- Führe den Befehl `cd "[Der Pfad zu Deinem Arbeitsverzeichnis]"` aus, um zum
Arbeitsbereich zu wechseln (z.B. `cd "C:\Users\Daniel Appenmaier\Java"`)
diff --git a/docs/additional-material/instructions/maven.md b/docs/additional-material/instructions/maven.md
index ba7c8d73ae..55fe172a2d 100644
--- a/docs/additional-material/instructions/maven.md
+++ b/docs/additional-material/instructions/maven.md
@@ -5,7 +5,7 @@ sidebar_position: 20
tags: [maven]
---
-:::info
+:::tip
Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/) und
[Eclipse](https://www.eclipse.org/)
@@ -14,6 +14,9 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/) und
## Maven-Projekt anlegen
+Ein neues Maven-Projekt wird direkt in Eclipse angelegt. Der Projektordner
+sollte im Git-Arbeitsbereich liegen, damit er versioniert werden kann.
+
- Starte Eclipse
- Führe die Funktion **File - New - Maven Project** aus
- Markiere die Option **Create a simple project (skip archetype selection)**,
@@ -33,6 +36,9 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/) und
## Java-Version und Codierung festlegen
+Die Java-Version und die Zeichenkodierung werden in der _pom.xml_ über
+Properties konfiguriert.
+
- Starte Eclipse
- Navigiere in der View _Package Explorer_ zu Deinem Maven-Projekt
- Navigiere in Deinem Maven-Projekt zur Datei _pom.xml_ und öffne diese
@@ -53,6 +59,9 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/) und
## JavaDoc erstellen
+Das JavaDoc-Maven-Plugin generiert eine HTML-Dokumentation aus den
+Javadoc-Kommentaren im Quellcode.
+
- Starte Eclipse
- Navigiere in der View _Package Explorer_ zu Deinem Maven-Projekt
- Navigiere in Deinem Maven-Projekt zur Datei _pom.xml_ und öffne diese
@@ -87,6 +96,9 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/) und
## Ausführbare JAR-Datei erstellen
+Das Shade-Plugin verpackt das Projekt samt aller Abhängigkeiten in eine
+ausführbare Über-JAR.
+
- Starte Eclipse
- Navigiere in der View _Package Explorer_ zu Deinem Maven-Projekt
- Navigiere in Deinem Maven-Projekt zur Datei _pom.xml_ und öffne diese
@@ -104,7 +116,7 @@ Benötigte Tools: [JDK](https://www.oracle.com/java/technologies/downloads/) und
org.apache.maven.plugins
maven-shade-plugin
- [Version]]
+ [Version]
package
diff --git a/docs/additional-material/tools/debugging.mdx b/docs/additional-material/tools/debugging.mdx
new file mode 100644
index 0000000000..3d5c9d8e79
--- /dev/null
+++ b/docs/additional-material/tools/debugging.mdx
@@ -0,0 +1,146 @@
+---
+title: Debugging
+description: ''
+sidebar_position: 50
+tags: [debugging]
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+Debugging bezeichnet den Prozess des Auffindens und Behebens von Fehlern
+(_Bugs_) in einem Programm. Fehler lassen sich in drei Kategorien einteilen:
+_Syntaxfehler_ werden bereits beim Kompilieren erkannt, _Laufzeitfehler_ treten
+erst während der Programmausführung auf (z.B. eine `NullPointerException`), und
+_logische Fehler_ führen zu einem falschen Ergebnis, ohne dass das Programm
+abstürzt. Während Syntaxfehler direkt von der IDE gemeldet werden, erfordern
+Laufzeit- und logische Fehler den Einsatz eines _Debuggers_.
+
+Ein Debugger ermöglicht es, ein Programm kontrolliert auszuführen, an beliebigen
+Stellen anzuhalten und den Zustand von Variablen sowie den Programmfluss zu
+inspizieren. Moderne IDEs wie [Eclipse](https://eclipseide.org/) oder
+[IntelliJ IDEA](https://www.jetbrains.com/idea/) verfügen über einen
+integrierten Debugger.
+
+## Weiterführende Links
+
+Die folgenden Ressourcen bieten eine vertiefte Einführung in das Debugging mit
+den gängigsten Java-IDEs.
+
+- [Eclipse Debugging Guide](https://www.eclipse.org/community/eclipse_newsletter/2017/june/article1.php)
+- [IntelliJ IDEA – Debug Code](https://www.jetbrains.com/help/idea/debugging-code.html)
+- [Visualizing Execution with Java Visualizer](https://pythontutor.com/java.html)
+
+## Breakpoints
+
+Ein _Breakpoint_ (Haltepunkt) markiert eine Zeile im Quellcode, an der die
+Programmausführung pausiert werden soll. Sobald der Debugger die markierte Zeile
+erreicht, hält er an – noch bevor die Anweisung in dieser Zeile ausgeführt wird.
+Anschließend lassen sich Variablenwerte und der Aufrufstack inspizieren.
+
+```mermaid
+flowchart LR
+ a[Programm im\nDebug-Modus starten]
+ b{Breakpoint\nerreicht?}
+ c[Ausführung\npausieren]
+ d[Zustand\ninspizieren]
+ e[Schritt\nausführen]
+ f[Programm\nendet]
+
+ a --> b
+ b -- Nein --> f
+ b -- Ja --> c --> d --> e --> b
+```
+
+## Debug-Ansichten
+
+Beim Debuggen stehen in der IDE mehrere spezialisierte Ansichten zur Verfügung,
+die gemeinsam ein vollständiges Bild des aktuellen Programmzustands liefern.
+
+| Ansicht | Beschreibung |
+| ----------- | ---------------------------------------------------------------------------- |
+| Variables | Zeigt alle aktuell sichtbaren Variablen und deren Werte |
+| Breakpoints | Listet alle gesetzten Breakpoints und ermöglicht das Aktivieren/Deaktivieren |
+| Call Stack | Zeigt die aktuelle Aufrufhierarchie der Methoden |
+| Console | Gibt die Standardausgabe des laufenden Programms aus |
+| Expressions | Wertet beliebige Ausdrücke im aktuellen Kontext aus |
+
+## Schrittweise Ausführung
+
+Nach dem Pausieren an einem Breakpoint stehen verschiedene Schritt-Befehle zur
+Verfügung, um die Programmausführung gezielt fortzusetzen und den Kontrollfluss
+zu verfolgen.
+
+
+
+
+**Step Over** (`F6` in Eclipse / `F8` in IntelliJ) führt die aktuelle Zeile
+vollständig aus und hält in der nächsten Zeile derselben Methode an.
+Methodenaufrufe werden dabei als ein Schritt behandelt – der Debugger springt
+nicht in die aufgerufene Methode hinein.
+
+```java title="Beispiel" showLineNumbers
+int a = 5; // <- Debugger hält hier an
+int b = add(a); // Step Over: add() wird ausgeführt, aber nicht betreten
+int c = b * 2; // <- Debugger hält hier an nach Step Over
+```
+
+
+
+
+**Step Into** (`F5` in Eclipse / `F7` in IntelliJ) springt in den Rumpf des
+Methodenaufrufs in der aktuellen Zeile hinein, sodass dessen Ausführung Schritt
+für Schritt verfolgt werden kann.
+
+```java title="Beispiel" showLineNumbers
+int a = 5; // <- Debugger hält hier an
+int b = add(a); // Step Into: Debugger springt in add() hinein
+int c = b * 2;
+```
+
+
+
+
+**Step Return** (`F7` in Eclipse / `Shift+F8` in IntelliJ) führt die restliche
+aktuelle Methode vollständig aus und hält nach der Rückkehr in der aufrufenden
+Methode an. Dieser Befehl wird typischerweise eingesetzt, wenn man versehentlich
+in eine Methode hineingesprungen ist.
+
+
+
+
+**Resume** (`F8` in Eclipse / `F9` in IntelliJ) setzt die Programmausführung
+fort, bis der nächste Breakpoint erreicht wird oder das Programm regulär endet.
+
+
+
+
+## Bedingte Breakpoints
+
+Ein _bedingter Breakpoint_ pausiert die Ausführung nur dann, wenn eine
+angegebene Bedingung wahr ist. Das ist besonders nützlich, wenn ein Fehler nur
+unter bestimmten Umständen auftritt – etwa bei einem konkreten
+Schleifendurchlauf oder einem bestimmten Parameterwert.
+
+```java title="Example: Fehler tritt nur bei i == 42 auf" showLineNumbers
+for (int i = 0; i < 100; i++) {
+ process(i); // <- bedingter Breakpoint: i == 42
+}
+```
+
+In Eclipse wird ein bedingter Breakpoint über **Rechtsklick auf den Breakpoint →
+Breakpoint Properties → Enable Condition** gesetzt. In IntelliJ IDEA über
+**Rechtsklick auf den Breakpoint → More → Condition**.
+
+## Häufige Fehler und deren Ursachen
+
+Die folgende Tabelle listet häufig auftretende Laufzeitausnahmen in Java und
+deren typische Ursachen auf, um die Fehlersuche zu beschleunigen.
+
+| Ausnahme | Typische Ursache |
+| -------------------------------- | ------------------------------------------------------------ |
+| `NullPointerException` | Zugriff auf ein Objekt, das `null` ist |
+| `ArrayIndexOutOfBoundsException` | Zugriff auf einen Index außerhalb der Array-Grenzen |
+| `ClassCastException` | Ungültige Typumwandlung zur Laufzeit |
+| `StackOverflowError` | Unendliche Rekursion |
+| `NumberFormatException` | Ungültige Zeichenkette beim Parsen (z.B. `Integer.parseInt`) |
diff --git a/docs/additional-material/tools/genai-tools.md b/docs/additional-material/tools/genai-tools.md
index c759cde98f..3a431ae0f4 100644
--- a/docs/additional-material/tools/genai-tools.md
+++ b/docs/additional-material/tools/genai-tools.md
@@ -7,32 +7,25 @@ tags: [genai]
import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
-Generative KI (GenAI) bezeichnet KI-Systeme, die auf Grundlage neuronaler Netze
-Inhalte wie Texte, Bilder, Videos, Musik, Quellcode etc. generieren können.
-GenAI bildet damit die Grundlage für moderne Chatbots wie ChatGPT, Gemini oder
-LeChat. Im Gegensatz zu "traditionellen" KI-Systemen, deren Aufgaben i.d.R.
-darin bestehen, Muster zu erkennen, Daten zu klassifizieren oder Zusammenhänge
-zu erkennen, kann GenAI mittels statistischer Wahrscheinlichkeiten und
-tiefgreifender Mustererkennung neuartige Inhalte erzeugen, die nicht Teil der
-Trainingsdaten waren. Schlüsselmodelle sind hierbei _Large Language Models_
-(LLMs) für Texte sowie Diffunsionsmodelle und _Generative Adversarial Networks_
-(GANs) für Bilder und Videos. Moderne Chatbots simulieren menschliche
-Konversationen über Text und Sprache und nutzen dabei LLMs, um dynamisch,
-kontextabhängig und zusammenhängend zu antworten. KI-gestützte Assistenzsysteme
-(Co-Pilots) wie Microsoft 365 Copilot und GitHub Copilot dagegen sind direkt in
-eine Anwendung (z.B. Textverarbeitungsprogramm, Tabellenkalkulationsprogramm,
-IDE) integriert und unterstützen den menschlichen Anwender aktiv, ohne dabei die
-Kontrolle zu übernehmen. Sie arbeiten quasi _parallel_ zum Anwender.
+Generative KI (GenAI) bezeichnet KI-Systeme, die auf Basis neuronaler Netze
+Inhalte wie Texte, Bilder, Videos, Musik oder Quellcode erzeugen. Im Unterschied
+zu "traditionellen" KI-Systemen, die Muster erkennen oder Daten klassifizieren,
+kann GenAI mittels statistischer Wahrscheinlichkeiten neuartige Inhalte
+generieren, die nicht Teil der Trainingsdaten waren. Schlüsseltechnologien sind
+_Large Language Models_ (LLMs) für Texte sowie Diffusionsmodelle und _Generative
+Adversarial Networks_ (GANs) für Bilder und Videos. Moderne Chatbots wie
+ChatGPT, Gemini oder LeChat nutzen LLMs, um kontextabhängig und zusammenhängend
+zu antworten. KI-gestützte Assistenzsysteme (Co-Pilots) wie Microsoft 365
+Copilot oder GitHub Copilot sind dagegen direkt in eine Anwendung integriert und
+unterstützen den Anwender aktiv, ohne die Kontrolle zu übernehmen.
## Prompt Engineering
-Prompt Engineering ist die Disziplin der Entwicklung und Optimierung von
-Eingaben (Prompts) mit dem Ziel, vorhersagbare, präzise und qualitativ
-hochwertige Ausgaben von generativen Modellen zu bekommen, die den spezifischen
-Anforderungen entsprechen. Die Grundprinzipien eines guten Prompts sind
-Klarheit, Kontext und Struktur. Um die Qualität von Prompts zu erhöhen und damit
-bessere, präzisere und zuverlässigere Ausgaben zu erhalten, können
-unterschiedliche Techniken verwendet werden.
+Prompt Engineering ist die Disziplin der gezielten Formulierung von Eingaben
+(Prompts), um von einem generativen Modell vorhersagbare, präzise und
+hochwertige Ausgaben zu erhalten. Ein guter Prompt zeichnet sich durch Klarheit,
+Kontext und Struktur aus. Die folgenden Techniken helfen dabei, die Qualität von
+Prompts zu verbessern.
@@ -109,22 +102,17 @@ Wenn der Zug 20 Minuten Verspätung hat, wann kommt er in B an?
## Vibe Coding
-Vibe Coding beschreibt eine neuartige Methode der Softwareentwicklung, bei der
-ein LLM zur Generierung des benötigten Quellcodes genutzt wird. Der Begriff
-wurde maßgeblich von OpenAI-Mitbegründer Andrej Karpathy geprägt und beschreibt
-die entspannte Zusammenarbeit mit der KI, bei der sich der Softwareentwickler
-voll und ganz auf den positiven Workflow und die inspirierende Atmosphäre mit
-der KI einlässt. Im Unterschied zur herkömmlichen Softwareentwicklung, bei der
-der Softwareentwickler selbst für das Erzeugen des Quellcodes zuständig ist,
-steht beim Vibe Coding die klare Beschreibung der Funktionalität in natürlicher
-Sprache durch Prompts im Vordergrund. Der konkrete Quellcode dagegen wird von
-der LLM erzeugt. Es handelt sich daher im Kern um eine Anwendung des Prompt
-Engineerings auf die Softwareentwicklung. Einsatzgebiete sind unter Anderem das
-Rapid Prototyping, die Erstellung von _Minimal Viable Products_ (MVPs) sowie das
-automatische Erzeugen von Boilerplate-Code. Nachteil von Vibe Coding ist vor
-allem eine stark schwankende Softwarequalität und ein damit verbundener erhöhter
-Wartungsaufwand. Es eignet sich daher nur bedingt für komplexe
-Softwareanwendungen oder Softwareanwendungen mit einem hohen Qualitätsanspruch.
+Vibe Coding ist eine Methode der Softwareentwicklung, bei der ein LLM den
+Quellcode auf Basis natürlichsprachlicher Beschreibungen generiert. Der Begriff
+wurde von OpenAI-Mitbegründer Andrej Karpathy geprägt. Im Unterschied zur
+herkömmlichen Softwareentwicklung steht nicht das Schreiben von Code im
+Vordergrund, sondern die klare Beschreibung der gewünschten Funktionalität durch
+Prompts — das LLM übernimmt die Implementierung. Vibe Coding ist damit im Kern
+eine Anwendung des Prompt Engineerings auf die Softwareentwicklung.
+Einsatzgebiete sind unter anderem Rapid Prototyping, die Erstellung von _Minimal
+Viable Products_ (MVPs) und das Erzeugen von Boilerplate-Code. Nachteil ist eine
+oft schwankende Softwarequalität und ein erhöhter Wartungsaufwand — Vibe Coding
+eignet sich daher nur bedingt für komplexe oder qualitätskritische Anwendungen.
```mermaid
flowchart
@@ -136,8 +124,7 @@ flowchart
a --> b --> c --> d --> b
```
-Im Beispiel soll ein einfacher Taschenrechner mit Hilfe von JavaFX entwickelt
-werden.
+Im Beispiel soll ein einfacher Taschenrechner mit JavaFX entwickelt werden.
diff --git a/docs/additional-material/tools/git.mdx b/docs/additional-material/tools/git.mdx
index 24df2c6976..4de38017fd 100644
--- a/docs/additional-material/tools/git.mdx
+++ b/docs/additional-material/tools/git.mdx
@@ -8,23 +8,20 @@ tags: [git]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Git stellt eine Software zur Verwaltung von Dateien mit integrierter
-Versionskontrolle dar, dessen Entwicklung unter Anderem von Linus Torvald (dem
-Erfinder von Linux) initiiert wurde. Die Versionskontrolle von Git ermöglicht
-den Zugriff auf ältere Entwicklungsstände, ohne dabei den aktuellen Stand zu
-verlieren. Zudem unterstützt Git die Verwaltung von verteilten Dateien an
-verschiedenen Aufbewahrungsorten. Diese Aufbewahrungsorte werden als
-_Repositorys_ bezeichnet. Man unterscheidet dabei zwischen lokalen Repositorys
-und remote Repositorys. Onlinedienste wie GitHub basieren auf Git und stellen
-dem Anwender Speicherplatz für remote Repositorys zur Verfügung.
+Git ist eine Software zur verteilten Versionskontrolle von Dateien. Entwickelt
+wurde Git unter anderem von Linus Torvalds, dem Erfinder von Linux. Die
+Versionskontrolle ermöglicht den Zugriff auf ältere Entwicklungsstände, ohne
+dabei den aktuellen Stand zu verlieren. Dateien werden an sogenannten
+_Repositorys_ abgelegt — entweder lokal auf dem eigenen Rechner oder auf einem
+Remote-Server. Onlinedienste wie GitHub basieren auf Git und stellen
+Speicherplatz für Remote-Repositorys bereit.
## Git Workflows
-Aufgrund der Flexibilität von Git gibt es keine standardisierten Prozesse für
-das Arbeiten mit Git. Ein Git Workflow stellt eine Anleitung zur Verwendung von
-Git dar, die eine konsistente und produktive Arbeitsweise ermöglichen soll. Für
-eine effiziente und fehlerfreie Arbeitsweise sollten daher alle Mitgleider eines
-Teams die gleichen Git Workflows verwenden.
+Ein Git Workflow ist eine Vereinbarung im Team darüber, wie Git genutzt wird. Er
+legt fest, wann Commits erstellt, welche Branch-Strategien eingesetzt und wie
+Änderungen synchronisiert werden. Einheitliche Workflows sind Voraussetzung für
+eine effiziente und fehlerarme Zusammenarbeit.
```mermaid
sequenceDiagram
@@ -57,12 +54,10 @@ sequenceDiagram
## Git Befehle
-Git bietet einen Vielzahl an verschiedenen Kommandozeilen-Befehlen um mit Git zu
-arbeiten. Eine ausführliche Dokumentation der einzelnen Befehle samt der
-dazugehörigen Optionen können auf der offiziellen
-[Git-Homepage](https://git-scm.com/docs) gefunden werden. Zudem kann mit dem
-Befehl `git --help` direkt in der Kommandozeile eine Kurzversion der
-Dokumentation ausgegeben werden.
+Git wird über Kommandozeilen-Befehle gesteuert. Die vollständige Dokumentation
+aller Befehle und Optionen ist auf der offiziellen
+[Git-Homepage](https://git-scm.com/docs) verfügbar. Mit `git --help` lässt sich
+eine Kurzübersicht direkt in der Kommandozeile ausgeben.
diff --git a/docs/additional-material/tools/markdown.mdx b/docs/additional-material/tools/markdown.mdx
index 3b397650fd..29951a4606 100644
--- a/docs/additional-material/tools/markdown.mdx
+++ b/docs/additional-material/tools/markdown.mdx
@@ -8,17 +8,18 @@ tags: [markdown]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Markdown stellt eine einfache Auszeichnungssprache dar, mit der man Text leicht
-formatieren kann. Sie wird häufig für Dokumentationen, README-Dateien und Blogs
-verwendet, weil sie leicht zu schreiben ist und sich mit Hilfe einer
-Konvertierungssoftware gut in HTML umwandeln lässt. Plattformen wie GitHub
-erweitern dabei oftmals die Standard-Syntax um hilfreiche Funktionen wie z.B.
-Tabellen, Nachrichtenblöcke und Code-Highlighting. Auch der Webseiten-Generator
+Markdown ist eine einfache Auszeichnungssprache zum Formatieren von Text. Sie
+wird häufig für Dokumentationen, README-Dateien und Blogs eingesetzt, da sie
+leicht zu schreiben ist und sich gut in HTML umwandeln lässt. Plattformen wie
+GitHub erweitern die Standardsyntax um Funktionen wie Tabellen,
+Nachrichtenblöcke und Code-Highlighting. Auch
[Docusaurus](https://docusaurus.io), mit dem diese Webseite erstellt wurde,
sowie die meisten GenAI-Chatbots verwenden Markdown.
## Hilfreiche Links
+Die folgenden Tools erleichtern das Arbeiten mit Markdown.
+
- [Tabellengenerator](https://www.tablesgenerator.com/)
- [Emoji-Cheat-Sheet](https://github.com/ikatyang/emoji-cheat-sheet/)
- [Quellcode-Formatierer](https://prettier.io/)
@@ -26,6 +27,8 @@ sowie die meisten GenAI-Chatbots verwenden Markdown.
## Textformatierungen
+Text lässt sich in Markdown mit wenigen Sonderzeichen formatieren.
+
| Syntax | Ergebnis |
| ------------------------------ | --------------- |
| `*Text*` oder `_Text_` | _Text_ |
@@ -40,6 +43,9 @@ sowie die meisten GenAI-Chatbots verwenden Markdown.
## Überschriften
+Überschriften werden mit Rauten (`#`) eingeleitet. Die Anzahl der Rauten
+bestimmt die Hierarchieebene.
+
@@ -63,6 +69,9 @@ sowie die meisten GenAI-Chatbots verwenden Markdown.
## Links und Abbildungen
+Links werden mit `[Anzeigetext](URL)` erstellt, Abbildungen mit
+``.
+
@@ -84,6 +93,8 @@ sowie die meisten GenAI-Chatbots verwenden Markdown.
## Listen
+Markdown unterstützt ungeordnete Listen, geordnete Listen und Aufgabenlisten.
+
@@ -130,6 +141,9 @@ sowie die meisten GenAI-Chatbots verwenden Markdown.
## Tabellen
+Tabellen werden mit senkrechten Strichen (`|`) und Trennzeilen aus Bindestrichen
+aufgebaut.
+
@@ -155,6 +169,9 @@ sowie die meisten GenAI-Chatbots verwenden Markdown.
## Codeblöcke
+Codeblöcke werden mit drei Gravis (` ``` `) eingeleitet und abgeschlossen.
+Optional kann die Programmiersprache für Syntax-Highlighting angegeben werden.
+
@@ -184,6 +201,8 @@ public class MainClass {
## Zitatblöcke
+Zitatblöcke werden mit einem vorangestellten `>` eingeleitet.
+
@@ -204,6 +223,9 @@ public class MainClass {
## Nachrichtenblöcke
+Nachrichtenblöcke heben wichtige Informationen visuell hervor. GitHub und
+Docusaurus unterstützen unterschiedliche Syntaxvarianten.
+
@@ -300,11 +322,14 @@ Eine deutliche Warnung
## Mermaid-Diagramme
+Mit Mermaid lassen sich Diagramme direkt im Markdown-Code beschreiben und
+rendern. GitHub und Docusaurus unterstützen Mermaid nativ.
+
````
-**Klassendiagram**
+**Klassendiagramm**
```mermaid
classDiagram
Gender --o Person
@@ -322,7 +347,7 @@ classDiagram
````
````
-**Flussdiagram**
+**Flussdiagramm**
```mermaid
flowchart LR
a[a]
@@ -348,7 +373,7 @@ pie
-**Klassendiagram**
+**Klassendiagramm**
```mermaid
classDiagram
@@ -365,7 +390,7 @@ classDiagram
}
```
-**Flussdiagram**
+**Flussdiagramm**
```mermaid
flowchart LR
@@ -400,13 +425,16 @@ erstellen.
## Fußnoten
+Fußnoten ermöglichen es, Quellenangaben oder ergänzende Hinweise ans Ende des
+Dokuments auszulagern.
+
```
Markdown [^1]
-[^1]: Eine einfache Auszeichnungssprache (vg. https://de.wikipedia.org/wiki/Markdown)
+[^1]: Eine einfache Auszeichnungssprache (vgl. https://de.wikipedia.org/wiki/Markdown)
```
@@ -423,6 +451,9 @@ Markdown [^1]
## Horizontale Linien
+Eine horizontale Linie wird durch drei aufeinanderfolgende Bindestriche (`---`)
+erzeugt.
+
diff --git a/docs/additional-material/tools/maven.md b/docs/additional-material/tools/maven.md
index b99a183871..c4a20e7a80 100644
--- a/docs/additional-material/tools/maven.md
+++ b/docs/additional-material/tools/maven.md
@@ -7,35 +7,33 @@ tags: [maven]
import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
-[Apache Maven (kurz Maven)](https://maven.apache.org/) ist ein sogenanntes
-Build-Automatisierungstool, welches hauptsächlich für Java-Projekte verwendet
-wird. Es hilft Entwicklern, den Build-Prozess eines Programmes zu vereinfachen
-und zu standardisieren. Maven verwendet hierzu eine Konfigurationsdatei namens
-_pom.xml_ (Project Object Model).
+[Apache Maven (kurz Maven)](https://maven.apache.org/) ist ein
+Build-Automatisierungstool für Java-Projekte. Es vereinfacht und standardisiert
+den Build-Prozess über eine zentrale Konfigurationsdatei namens _pom.xml_
+(Project Object Model).
## Merkmale
-- Automatisierung des Build-Prozesses: Maven automatisiert den Build-Prozess
- (Kompilieren, Testen, Verpacken und Bereitstellen)
-- Abhängigkeitsmanagement: Maven verwaltet Projekt-Abhängigkeiten wie externe
- Bibliotheken und Frameworks automatisch
-- Standardisierte Projektstruktur: Maven fördert eine standardisierte
- Projektstruktur, die es einfacher macht, Projekte zu verstehen und zu
- navigieren
-- Plugins: Maven unterstützt eine Vielzahl von Plugins, die zusätzliche
- Funktionalitäten bieten (z.B. Code-Analyse, Berichterstellung und
- Dokumentation)
-- Lebenszyklus-Management: Maven definiert einen standardisierten Lebenszyklus
- für den Build-Prozess
+Maven zeichnet sich durch folgende Eigenschaften aus:
+
+- Automatisierung des Build-Prozesses: Kompilieren, Testen, Verpacken und
+ Bereitstellen
+- Abhängigkeitsmanagement: externe Bibliotheken und Frameworks werden
+ automatisch verwaltet
+- Standardisierte Projektstruktur: erleichtert das Verstehen und Navigieren in
+ Projekten
+- Plugins: erweitern Maven um zusätzliche Funktionen wie Code-Analyse,
+ Berichterstellung und Dokumentation
+- Lebenszyklus-Management: definierter, standardisierter Ablauf des
+ Build-Prozesses
## Lebenszyklus-Phasen
-Maven kennt die drei Lebenszyklen `clean` zum Löschen aller Artefakte
-vergangener Builds, `default` zum Erstellen des Projekts sowie `site` zum
-Erstellen einer Dokumentationsseite. Jeder Lebenszyklus durchläuft hierbei
-verschiedene Phasen. Durch Plugins können diese um zusätzliche
-Verarbeitungsschritte erweitert werden. Nachfolgend dargestellt sind die
-wesentlichen Phasen des Default Lebenszyklus:
+Maven kennt drei Lebenszyklen: `clean` löscht alle Artefakte vergangener Builds,
+`default` erstellt das Projekt, und `site` generiert eine Dokumentationsseite.
+Jeder Lebenszyklus durchläuft dabei mehrere Phasen, die sich durch Plugins um
+zusätzliche Schritte erweitern lassen. Die folgende Tabelle zeigt die
+wesentlichen Phasen des Default-Lebenszyklus.
| Phase | Beschreibung |
| ---------- | ------------------------------------------------------------------------------------ |
@@ -49,11 +47,10 @@ wesentlichen Phasen des Default Lebenszyklus:
## Das Projektmodell
-Das Projektmodel umfasst neben allgemeinen Projekt-Angaben wie der `groupId`,
-der `artifactId` sowie der `version` auch sämtliche Abhängigkeiten zu externen
-Bibliotheken, die dadurch automatisch von Maven verwaltet werden. Zudem kann
-hier unter anderem der Build-Prozess konfiguriert und durch Plugins erweitert
-werden.
+Das Projektmodell enthält neben allgemeinen Projekt-Angaben wie `groupId`,
+`artifactId` und `version` auch alle Abhängigkeiten zu externen Bibliotheken.
+Zusätzlich lässt sich hier der Build-Prozess konfigurieren und durch Plugins
+erweitern.
```xml title="pom.xml" showLineNumbers
@@ -137,11 +137,11 @@ Berichtsseite.
-[Prettier](https://prettier.io/) ist ein weit verbreiterter
-Quellcode-Formatierer, der eine einheitliche Quellcode-Formatierung fördert.
-Durch die Einbindung des Goals `write` in die Lebenszyklus-Phase `compile` wird
+[Prettier](https://prettier.io/) ist ein weit verbreiteter
+Quellcode-Formatierer, der eine einheitliche Formatierung fördert. Durch die
+Einbindung des Goals `write` in die Lebenszyklus-Phase `compile` wird
sichergestellt, dass der Quellcode bei jedem Kompiliervorgang automatisch
-formattiert wird.
+formatiert wird.
```xml title="pom.xml (Auszug)" showLineNumbers
...
@@ -218,11 +218,16 @@ die Über-JAR bei jedem Verpacken erstellt wird.
## Hilfreiche Bibliotheken und Frameworks
+Die folgende Auswahl an Bibliotheken und Frameworks wird häufig in
+Java-Projekten eingesetzt und lässt sich einfach als Maven-Abhängigkeit
+einbinden.
+
-Lombok ist eine beliebte Bibliothek zur Generierung von repetitiven Methoden
-(siehe auch [Lombok](../../documentation/lombok)).
+Lombok ist eine beliebte Bibliothek zur automatischen Generierung von
+Boilerplate-Code wie Getter, Setter und Konstruktoren (siehe auch
+[Lombok](../../documentation/lombok)).
```xml title="pom.xml (Auszug)" showLineNumbers
...
@@ -240,11 +245,10 @@ Lombok ist eine beliebte Bibliothek zur Generierung von repetitiven Methoden
-Simple Logging Facade for Java (SLF4J) ist eine beliebte
-Java-Protokollierungs-API, die es ermöglicht, den Quellcode um Protokolle zu
-erweitern, die anschließend an ein gewünschtes Protokoll-Framework (wie z.B.
-Log4J) weitergeleitet werden (siehe auch
-[Simple Logging Facade for Java (SLF4J)](../../documentation/slf4j)).
+SLF4J (Simple Logging Facade for Java) ist eine Protokollierungs-API, die den
+Quellcode von der konkreten Protokoll-Implementierung entkoppelt. Die
+eigentlichen Protokollmeldungen werden an ein Framework wie Log4J weitergeleitet
+(siehe auch [SLF4J](../../documentation/slf4j)).
```xml title="pom.xml (Auszug)" showLineNumbers
...
@@ -309,8 +313,8 @@ das hauptsächlich für das Testen von Anwendungen verwendet wird (siehe auch
-JavaFX stellt (vor allem in Verbindung mit Java FXML) ein State-of-the-Art
-Framework für das Erstellen von GUIs in Java dar (siehe auch
+JavaFX ist ein Framework für grafische Benutzeroberflächen in Java. In
+Verbindung mit Java FXML lassen sich Layout und Logik sauber trennen (siehe auch
[JavaFX](../../documentation/javafx)).
```xml title="pom.xml (Auszug)" showLineNumbers
diff --git a/docs/documentation/abstract-and-final.mdx b/docs/documentation/abstract-and-final.mdx
index 76bcf8b1eb..cb60b134fc 100644
--- a/docs/documentation/abstract-and-final.mdx
+++ b/docs/documentation/abstract-and-final.mdx
@@ -8,15 +8,14 @@ tags: [abstract, final]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Mit Hilfe der Schlüsselwörter `abstract` und `final` kann die Verwendung von
-Klassen vorgegeben bzw. eingeschänkt werden:
+Mit den Schlüsselwörtern `abstract` und `final` lässt sich die Verwendung von
+Klassen und Methoden einschränken oder vorschreiben:
- Abstrakte Klassen können nicht instanziiert werden
-- Abstrakte Methoden werden in abstrakten Klassen definiert, besitzen dort
- keinen Methodenrumpf und müssen in den abgeleiteten Klassen der abstrakten
- Klasse überschrieben werden
-- Finale Klassen können nicht abgeleitet werden
-- Finale Methoden können nicht überschrieben werden
+- Abstrakte Methoden werden in abstrakten Klassen deklariert, besitzen keinen
+ Methodenrumpf und müssen in allen abgeleiteten Klassen überschrieben werden
+- Finale Klassen können nicht von anderen Klassen abgeleitet werden
+- Finale Methoden können von Unterklassen nicht überschrieben werden
@@ -50,7 +49,7 @@ public final class Notebook extends Computer {
}
@Override
- public Cpu getCpu() {...} // Kompilierungsfehler
+ public Cpu getCpu() {...} // Kompilierungsfehler: finale Methode kann nicht überschrieben werden
...
}
```
@@ -59,10 +58,10 @@ public final class Notebook extends Computer {
```java title="MainClass.java" showLineNumbers
-public class MainClass extends Notebook { // Kompilierungsfehler
+public class MainClass extends Notebook { // Kompilierungsfehler: finale Klasse kann nicht erweitert werden
public static void main(String[] args) {
- Computer computer = new Computer("Mein Office PC"); // Kompilierungsfehler
+ Computer computer = new Computer("Mein Office PC"); // Kompilierungsfehler: abstrakte Klasse kann nicht instanziiert werden
}
}
diff --git a/docs/documentation/activity-diagrams.md b/docs/documentation/activity-diagrams.md
index d11b58160c..085cd9219d 100644
--- a/docs/documentation/activity-diagrams.md
+++ b/docs/documentation/activity-diagrams.md
@@ -5,24 +5,20 @@ sidebar_position: 165
tags: [uml, activity-diagrams]
---
-Aktivitätsdiagramme sind ein Diagrammtyp der UML und gehören dort zum Bereich
-der Verhaltensdiagramme. Der Fokus von Aktivitätsdiagrammen liegt auf
-imperativen Verarbeitungsaspekten. Eine Aktivität stellt einen gerichteten
-Graphen dar, der über Knoten (Aktionen, Datenknoten und Kontrollknoten) und
-Kanten (Kontrollflüsse und Datenflüsse) verfügt:
+Aktivitätsdiagramme sind ein Diagrammtyp der UML und gehören zu den
+Verhaltensdiagrammen. Sie modellieren den Ablauf von Aktivitäten mit Fokus auf
+dem Kontroll- und Datenfluss. Eine Aktivität ist ein gerichteter Graph aus
+Knoten und Kanten:
-- Aktionen sind elementare Bausteine für beliebiges, benutzerdefiniertes
- Verhalten
-- Kontrollknoten steuern den Kontroll- und Datenfluss in einer Aktivität:
- - Startknoten: legen den Beginn der Aktivität fest
- - Endknoten: legen das Ende der Aktivität fest
- - Ablaufendknoten: legen das Ende eines Ablaufes fest
- - Verzweigungsknoten: ermöglichen die Verzweigung von Abläufen
- - Zusammenführungsknoten: ermöglichen die Zusammenführung von Abläufen
-- Datenknoten sind Hilfsknoten, die als ein- oder ausgehende Parameter einer
- Aktion verwendet werden können
-- Kontroll- und Datenflüsse legen Abläufe zwischen Vorgänger- und
- Nachfolger-Knoten fest
+- Aktionen sind elementare Bausteine für benutzerdefiniertes Verhalten.
+- Kontrollknoten steuern den Ablauf:
+ - Startknoten legen den Beginn der Aktivität fest.
+ - Endknoten legen das Ende der Aktivität fest.
+ - Ablaufendknoten legen das Ende eines einzelnen Ablaufzweigs fest.
+ - Verzweigungsknoten ermöglichen das Aufteilen von Abläufen.
+ - Zusammenführungsknoten führen Abläufe wieder zusammen.
+- Datenknoten dienen als ein- oder ausgehende Parameter einer Aktion.
+- Kontroll- und Datenflüsse verbinden Vorgänger- und Nachfolgeknoten.
```mermaid
stateDiagram-v2
diff --git a/docs/documentation/algorithms.mdx b/docs/documentation/algorithms.mdx
index db8562f063..aec2dd0c9f 100644
--- a/docs/documentation/algorithms.mdx
+++ b/docs/documentation/algorithms.mdx
@@ -8,12 +8,10 @@ tags: [algorithms]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Ein Algorithmus stellt ein Verfahren zur Lösung eines Problems mit einer
-endlichen Anzahl von Schritten dar. In der Prpgrammierung ist ein Algorithmus
-eine Reihe von Anweisungen, die festlegen, was und wie etwas getan werden muss.
-Zielsetzung ist dabei, aus einer gegebenen Eingabe eine entsprechende Ausgabe zu
-erhalten. Beispiele aus der realen Welt für Algorithmen sind Aufbauanleitungen,
-Rezepte, Spielanleitungen und Beipackzettel.
+Ein Algorithmus ist ein schrittweises Verfahren zur Lösung eines Problems mit
+einer endlichen Anzahl klar definierter Anweisungen. Er nimmt eine Eingabe
+entgegen und liefert eine entsprechende Ausgabe. Alltagsbeispiele für
+Algorithmen sind Kochrezepte, Aufbauanleitungen oder Beipackzettel.
```mermaid
flowchart LR
@@ -23,11 +21,11 @@ flowchart LR
output[Ausgabe]@{ shape: lean-r }
```
-Das nachfolgende Rezept beschreibt die Zubereitung von Pankcakes:
+Das nachfolgende Rezept beschreibt die Zubereitung von Pancakes:
-1. 3 Eiweiss zu festem Eischnee verarbeiten
-2. 3 Eigelb und 50g Zucker schaumig rühren
-3. 300g Mehl, 300g Milch, 1 TL Backpulver und etwas Salz unter die
+1. 3 Eiweiß zu festem Eischnee verarbeiten
+2. 3 Eigelb und 50 g Zucker schaumig rühren
+3. 300 g Mehl, 300 g Milch, 1 TL Backpulver und etwas Salz unter die
Eigelb-Zuckermasse rühren
4. Sollte der Teig zu fest sein, zusätzlich Milch unterrühren
5. Den Eischnee unter den Teig heben
@@ -44,34 +42,31 @@ ausführbares Programm bezeichnet man als Programmierung.
## Eigenschaften von Algorithmen
-Damit ein Verfahren als Algorithmus angesehen werden kann, muss es verschiedene
-Eigenschaften erfüllen:
+Damit ein Verfahren als Algorithmus gilt, muss es die folgenden Eigenschaften
+erfüllen:
-- Determiniertheit: Ein Verfahren ist deterministisch, wenn es bei beliebig
- häufiger Wiederholung für gleiche Eingabewerte und gleichen Rahmenbedingungen
- immer zum gleichen Ergebnis führt.
-- Eindeutigkeit (Determinismus): Ein Verfahren ist determiniert, wenn die
- Schrittfolge immer gleich ist und immer zu einem eindeutigen Ergebnis führt.
-- Endlichkeit (Terminiertheit): Ein Verfahren ist terministisch, wenn die Anzahl
- der Schritte endlich ist, also wenn das Verfahren nach endlichen Schritten ein
- Ergebnis liefert.
-- Korrektheit: Ein Verfahren ist korrekt, wenn es immer zu einem richtigen
- Ergebnis führt.
+- Determiniertheit: Bei gleicher Eingabe und gleichen Rahmenbedingungen führt
+ der Algorithmus immer zum gleichen Ergebnis.
+- Determinismus (Eindeutigkeit): Die Schrittfolge ist eindeutig festgelegt und
+ führt immer zu einem eindeutigen Ergebnis.
+- Terminiertheit (Endlichkeit): Der Algorithmus endet nach einer endlichen
+ Anzahl von Schritten.
+- Korrektheit: Der Algorithmus liefert für alle gültigen Eingaben das richtige
+ Ergebnis.
## Komplexität von Algorithmen
-Da der Zeitaufwand von Algorithmen aufgrund unterschiedlicher Faktoren
-(Hardware, parallele Verarbeitung, Eingabereihenfolge,…) nicht genau ermittelt
-werden kann, wird diese mit Hilfe der Landau-Notation 𝒪 (_Ordnung von_)
-dargestellt. Diese teilt Algorithmen in unterschiedliche Komplexitätsklassen
-(logarithmisch, linear, polynomial,…) ein. Die Komplexität einer Klasse ergibt
-sich dabei aus der Anzahl der Schritte, die abhängig von der Größe der
-Eingangsvariablen ausgeführt werden müssen.
+Da die Laufzeit eines Algorithmus von Faktoren wie Hardware, paralleler
+Verarbeitung oder der Eingabereihenfolge abhängt, wird sie nicht absolut
+gemessen, sondern mit der Landau-Notation 𝒪 (_Ordnung von_) beschrieben. Diese
+teilt Algorithmen in Komplexitätsklassen ein (z.B. logarithmisch, linear,
+polynomial) und gibt an, wie viele Schritte der Algorithmus in Abhängigkeit von
+der Eingabegröße benötigt.
## Suchalgorithmen
-Suchalgorithmen sollen innerhalb einer Datensammlung einen oder mehrere
-Datensätze mit bestimmten Eigenschaften finden.
+Suchalgorithmen finden innerhalb einer Datensammlung einen oder mehrere Einträge
+mit bestimmten Eigenschaften.
| Algorithmus | Komplexität Best Case | Komplexität Average Case | Komplexität Worst Case |
| ------------------- | --------------------- | ------------------------ | ---------------------- |
@@ -82,10 +77,10 @@ Datensätze mit bestimmten Eigenschaften finden.
-Bei der Linearsuche werden alle Einträge einer Datensammlung nacheinander
-durchlaufen, d.h. eine Suche kann im besten Fall beim ersten Eintrag und im
-schlechtesten Fall beim letzten Eintrag beendet sein. Bei einer erfolglosen
-Suche müssen alle Einträge durchlaufen werden.
+Bei der Linearsuche werden alle Einträge der Datensammlung nacheinander
+durchlaufen. Im besten Fall wird das gesuchte Element beim ersten Zugriff
+gefunden, im schlechtesten Fall erst beim letzten. Bei einer erfolglosen Suche
+werden alle Einträge durchlaufen.
Im nachfolgenden Beispiel wird die Zahlenfolge
`12, 16, 36, 49, 50, 68, 70, 76, 99` nach dem Wert 70 durchsucht.
@@ -112,10 +107,10 @@ verbessert werden.
-Bei der Binärsuche wird die sortierte Sammlung schrittweise halbiert.
-Anschließend wird nur noch in der jeweils passenden Hälfte weitergesucht. Die
-Binärsuche folgt damit dem Teile-und-Herrsche-Prinzip und ist i.d.R. schneller
-als die Linearsuche, setzt aber eine sortierte Sammlung voraus.
+Bei der Binärsuche wird die sortierte Sammlung schrittweise halbiert, und die
+Suche wird nur in der passenden Hälfte fortgesetzt. Dieses Teile-und-Herrsche-
+Prinzip macht die Binärsuche deutlich schneller als die Linearsuche, setzt aber
+eine sortierte Sammlung voraus.
Im nachfolgenden Beispiel wird die Zahlenfolge
`12, 16, 36, 49, 50, 68, 70, 76, 99` nach dem Wert 70 durchsucht.
@@ -154,10 +149,10 @@ Zahl ist, verwendet.
-Die Interpolationssuche basiert auf der Binärsuche, halbiert die Sammlung aber
-nicht, sondern versucht, durch Interpolation, einen geeigneteren Teiler zu
-ermitteln. Dieser wird mit Hilfe der Formel
-`t = ⌊𝑙 + ((𝑠 − 𝑑[𝑙]) / (𝑑[𝑟] − 𝑑[𝑙])) ∗ (𝑟 − 𝑙)⌋` ermittelt.
+Die Interpolationssuche basiert auf der Binärsuche, berechnet den Teilungspunkt
+jedoch nicht als Mitte, sondern durch Interpolation mit der Formel
+`t = ⌊𝑙 + ((𝑠 − 𝑑[𝑙]) / (𝑑[𝑟] − 𝑑[𝑙])) ∗ (𝑟 − 𝑙)⌋`. Dadurch kann sie bei
+gleichmäßig verteilten Daten schneller konvergieren.
Im nachfolgenden Beispiel wird die Zahlenfolge
`12, 16, 36, 49, 50, 68, 70, 76, 99` nach dem Wert 70 durchsucht.
@@ -191,14 +186,12 @@ Teiler, ⌊ ⌋ = untere Gaußklammer
## Sortieralgorithmen
-Sortieralgorithmen sollen eine möglichst effiziente Speicherung von Daten und
-deren Auswertung ermöglichen. Man unterscheidet dabei zwischen einfachen und
-rekursiven Sortieralgorithmen. Zusätzlich wird bei Sortierverfahren zwischen
-stabilen und nichtstabilen Verfahren unterschieden. Bei stabilen
-Sortierverfahren bleibt die Reihenfolge von gleich großen Datensätzen bei der
-Sortierung erhalten. Die Platzkomplexität eines Sortierverfahrens schließlich
-gibt an, ob zusätzlicher Speicherplatz für Zwischenergebnisse unabhängig von der
-Anzahl Daten ist (_in-place_) oder nicht (_out-of-place_).
+Sortieralgorithmen bringen eine Datensammlung in eine definierte Reihenfolge.
+Man unterscheidet zwischen einfachen und rekursiven Verfahren sowie zwischen
+stabilen (gleichwertige Elemente behalten ihre ursprüngliche Reihenfolge) und
+nicht-stabilen Verfahren. Arbeitet ein Algorithmus ohne zusätzlichen
+Speicherplatz aus, bezeichnet man ihn als _in-place_, andernfalls als
+_out-of-place_.
| Algorithmus | Komplexität Best Case | Komplexität Average Case | Komplexität Worst Case | Stabil | In-Place |
| ------------- | --------------------- | ------------------------ | ---------------------- | ------ | -------- |
@@ -212,10 +205,9 @@ Anzahl Daten ist (_in-place_) oder nicht (_out-of-place_).
-Der Bubblesort verfolgt die Idee, das größere Blasen schneller aufsteigen als
-kleinere. Dementsprechend werden beim Bubblesort Nachbarelemente miteinander
-verglichen und gegebenenfalls vertauscht, so dass am Ende eines Durchlaufs das
-jeweils größte Element am Ende des noch unsortierten Teils steht.
+Beim Bubblesort werden benachbarte Elemente miteinander verglichen und bei
+falscher Reihenfolge getauscht. Nach jedem Durchlauf steht das größte Element am
+Ende des noch unsortierten Bereichs — ähnlich einer aufsteigenden Blase.
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| ----- | --- | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
@@ -232,10 +224,9 @@ jeweils größte Element am Ende des noch unsortierten Teils steht.
-Beim Insertionsort wird dem unsortierten Teil der Ausgangsdaten ein beliebiges
-Element entnommen (z.B. das jeweils erste) und an der richtigen Stelle im
-sortierten Teil wieder eingefügt. Beim Einfügen wird das entnommene Element mit
-den bereits sortierten Elementen verglichen.
+Beim Insertionsort wird jeweils ein Element aus dem unsortierten Bereich
+entnommen und an der richtigen Position im sortierten Bereich eingefügt. Das
+Verfahren entspricht dem Sortieren von Spielkarten in der Hand.
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| ----- | --- | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
@@ -252,8 +243,8 @@ den bereits sortierten Elementen verglichen.
-Beim Selectionsort wird dem unsortierten Teil der Ausgangsdaten das jeweils
-kleinste Element entnommen und dem sortierten Teil angehängt.
+Beim Selectionsort wird in jedem Durchlauf das kleinste Element aus dem
+unsortierten Bereich gesucht und an das Ende des sortierten Bereichs angefügt.
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| ----- | --- | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
@@ -270,11 +261,10 @@ kleinste Element entnommen und dem sortierten Teil angehängt.
-Beim Quicksort wird die jeweilige Sammlung anhand eines beliebigen Elements
-(i.d.R. das mittlere Element) in zwei Hälften aufgeteilt: eine Hälfte mit
-Elementen kleiner oder gleich dem Teiler-Element und eine Hälfte mit Elementen
-größer dem Teiler-Element. Der Quicksort setzt folglich auf das
-Teile-und-Herrsche-Prinzip.
+Beim Quicksort wird ein Pivot-Element gewählt (in der Regel das mittlere
+Element), und die Sammlung wird in zwei Teile aufgeteilt: Elemente kleiner oder
+gleich dem Pivot und Elemente größer als das Pivot. Das Verfahren wird rekursiv
+auf beide Teile angewendet (Teile-und-Herrsche-Prinzip).
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| ----- | ---- | ---- | ------ | ------ | ------ | ------ | ------ |
@@ -315,9 +305,9 @@ Zahl ist, verwendet.
-Beim Mergesort wird die Ausgangsliste zunächst in kleinere Listen zerlegt, die
-anschließend im Reißverschlussverfahren wieder zusammengefügt bzw. verschmolzen
-werden.
+Beim Mergesort wird die Liste zunächst rekursiv in Einzelelemente zerlegt.
+Anschließend werden die Teillisten im Reißverschlussverfahren sortiert
+zusammengeführt (gemergt).
```mermaid
flowchart
@@ -369,12 +359,11 @@ flowchart
-Beim Heapsort werden die Daten zunächst in einen binären Max-Heap überführt,
-d.h. in einen Binärbaum, bei dem jeder Elternknoten größer ist als seine
-Kindknoten. Anschließend wird in jedem Durchlauf das jeweils letzte Element mit
-dem Wurzelknoten ausgetauscht und anschließend durch Vergleichen und Austauschen
-sichergestellt, dass weiterhin alle Knoten die Heap-Bedingung erfüllen. Dieser
-Schritt wird als Heapify oder Versickern bezeichnet.
+Beim Heapsort werden die Daten zunächst in einen binären Max-Heap überführt —
+einen Binärbaum, in dem jeder Elternknoten größer ist als seine Kindknoten.
+Anschließend wird in jedem Durchlauf das größte Element (die Wurzel) entnommen
+und durch das letzte Element ersetzt, woraufhin die Heap-Eigenschaft
+wiederhergestellt wird (Heapify / Versickern).
```mermaid
flowchart TD
diff --git a/docs/documentation/array-lists.md b/docs/documentation/array-lists.md
index f0508ac69a..ede6b630ec 100644
--- a/docs/documentation/array-lists.md
+++ b/docs/documentation/array-lists.md
@@ -5,10 +5,9 @@ sidebar_position: 141
tags: [collections, arrays, lists]
---
-Um das Arbeiten mit Feldern zu erleichtern, stellt die Java API die Klasse
-`ArrayList` zur Verfügung. Diese stellt eine veränderbare Liste dynamischer
-Größe auf Basis eines Feldes dar und bietet hilfreiche Methoden zum Hinzufügen,
-Ändern, Löschen und Lesen von Listelementen.
+Die Klasse `ArrayList` aus der Java API stellt eine veränderbare Liste
+dynamischer Größe auf Basis eines Feldes bereit und bietet Methoden zum
+Hinzufügen, Ändern, Löschen und Lesen von Elementen.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -19,12 +18,28 @@ public class MainClass {
names.add("Peter");
names.add("Lisa");
- System.out.println(names.size());
- System.out.println(names.get(0));
- names.set(0, "Max");
- names.add("Heidi");
- names.remove(0);
+ System.out.println(names.size()); // Anzahl der Elemente
+ System.out.println(names.get(0)); // Element an Index 0 lesen
+ names.set(0, "Max"); // Element an Index 0 ersetzen
+ names.add("Heidi"); // Element am Ende hinzufügen
+ names.remove(0); // Element an Index 0 entfernen
}
}
```
+
+Die folgende Tabelle zeigt häufig verwendete Methoden der Klasse `ArrayList`.
+
+| Methode | Rückgabetyp | Beschreibung |
+| ----------------------- | ----------- | --------------------------------------------------- |
+| `add(e: E)` | `boolean` | Fügt ein Element am Ende hinzu |
+| `add(index: int, e: E)` | `void` | Fügt ein Element an der angegebenen Position ein |
+| `get(index: int)` | `E` | Gibt das Element an der angegebenen Position zurück |
+| `set(index: int, e: E)` | `E` | Ersetzt das Element an der angegebenen Position |
+| `remove(index: int)` | `E` | Entfernt das Element an der angegebenen Position |
+| `remove(o: Object)` | `boolean` | Entfernt das erste Vorkommen des Objekts |
+| `size()` | `int` | Gibt die Anzahl der Elemente zurück |
+| `contains(o: Object)` | `boolean` | Prüft, ob das Objekt in der Liste enthalten ist |
+| `indexOf(o: Object)` | `int` | Gibt den Index des ersten Vorkommens zurück |
+| `isEmpty()` | `boolean` | Prüft, ob die Liste leer ist |
+| `clear()` | `void` | Entfernt alle Elemente |
diff --git a/docs/documentation/arrays.md b/docs/documentation/arrays.md
index 090ad3f21a..78c6411737 100644
--- a/docs/documentation/arrays.md
+++ b/docs/documentation/arrays.md
@@ -5,10 +5,10 @@ sidebar_position: 110
tags: [arrays]
---
-Wenn eine große Menge an Daten verarbeitet werden soll, kann man auf spezielle
-Datenstruktur-Variablen, sogenannte _Felder_ (Arrays), zurückgreifen. Die
-einzelnen Speicherplätze in einem Feld werden als Elemente bezeichnet, die über
-einen Index angesprochen werden können.
+Wenn eine größere Menge gleichartiger Daten verarbeitet werden soll, bieten sich
+_Felder_ (Arrays) an. Ein Feld ist eine Datenstruktur, die eine feste Anzahl von
+Elementen desselben Typs zusammenfasst. Die einzelnen Elemente werden über einen
+nullbasierten Index angesprochen.
| 0 | 1 | 2 | 3 | 4 |
| ---- | ----- | ---- | --- | ----- |
@@ -16,10 +16,10 @@ einen Index angesprochen werden können.
## Erzeugen von Feldern
-Da es sich bei Feldern um Objekte handelt, müssen diese vor Verwendung erzeugt
-werden. Bei der Erzeugung muss immer die Länge des Feldes (d.h. die Anzahl der
-Elemente) angegeben werden. Jedes Feld verfügt über das Attribut `length`,
-welches die Länge des Feldes enthält.
+Da Felder Objekte sind, müssen sie vor der Verwendung mit dem `new`-Operator
+erzeugt werden. Bei der Erzeugung muss die Länge des Feldes (Anzahl der
+Elemente) angegeben werden. Jedes Feld besitzt das Attribut `length`, das die
+Länge enthält.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -36,15 +36,15 @@ public class MainClass {
:::info
-Felder werden zwar mit Hilfe des new-Operators erzeugt, besitzen aber keinen
+Felder werden zwar mit dem `new`-Operator erzeugt, besitzen aber keinen
Konstruktor.
:::
## Zugriff auf Feldelemente
-Der Zugriff auf die Elemente eines Feldes erfolgt über die Angabe des
-entsprechenden Index.
+Der Zugriff auf ein Element erfolgt über den zugehörigen Index in eckigen
+Klammern. Der Index beginnt in Java bei 0.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -52,6 +52,7 @@ public class MainClass {
public static void main(String[] args) {
int[] ids = {4, 8, 15, 16, 23, 42};
+ // alle Elemente über den Index ausgeben
for (int i = 0; i < ids.length; i++) {
System.out.println(ids[i]);
}
@@ -62,14 +63,14 @@ public class MainClass {
:::info
-Der Index beginnt bei Java bei 0.
+Der Index beginnt in Java bei 0.
:::
## Der Parameter _String[] args_
-Der Parameter `String[] args` der main-Methode ermöglicht es dem Anwender, der
-ausführbaren Klasse beim Aufruf Informationen mitzugeben.
+Der Parameter `String[] args` der main-Methode ermöglicht es, der Anwendung beim
+Aufruf über die Kommandozeile Argumente zu übergeben.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -86,9 +87,9 @@ public class MainClass {
## Variable Argumentlisten (VarArgs)
Variable Argumentlisten (VarArgs) ermöglichen die Definition von Methoden, denen
-beliebig viele Werte eines Datentyps mitgegeben werden können. Die
-Parameterliste einer Methode kann allerdings nur eine variable Argumentliste
-beinhalten und diese muss immer am Ende der Parameterliste stehen.
+eine beliebige Anzahl von Werten desselben Datentyps übergeben werden kann. Eine
+Parameterliste darf nur eine VarArgs-Liste enthalten, und diese muss stets am
+Ende der Parameterliste stehen.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/binary-numbers.mdx b/docs/documentation/binary-numbers.mdx
index e3c9669404..9f48687097 100644
--- a/docs/documentation/binary-numbers.mdx
+++ b/docs/documentation/binary-numbers.mdx
@@ -9,15 +9,14 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Informationen wie Zahlen und Zeichen werden im Computer in Form von sogenannten
-_Bits_ (Binary Digits) gespeichert. Ein Bit stellt dabei die kleinstmögliche
-Informationseinheit dar und kann zwei Zustände einnehmen: 0 und 1 (bzw. "an" und
-"aus", "wahr" und "falsch", "Strom fließt" und "Strom fließt nicht"). Zahlen,
-die mit Hilfe von Bits dargestellt werden, bezeichnet man als Binärzahlen, das
-dazugehörige Zahlensystem als Binärsystem. Zahlensysteme wie das Binärsystem
-oder das Dezimalsystem legen fest, wie Zahlen dargestellt werden. Anhand des
-Namens lässt sich dabei ableiten, wie viele Ziffern zur Darstellung einer Zahl
-zur Verfügung stehen. Um Unklarheiten zu vermeiden, können Zahlen um einen nach-
-und tiefgestellten Index ergänzt werden (2 = Binärsystem, 8 = Oktalsystem, 10 =
+_Bits_ (Binary Digits) gespeichert. Ein Bit ist die kleinstmögliche
+Informationseinheit und kann zwei Zustände annehmen: 0 und 1 (bzw. „an" und
+„aus", „wahr" und „falsch", „Strom fließt" und „Strom fließt nicht"). Zahlen,
+die mit Hilfe von Bits dargestellt werden, nennt man _Binärzahlen_, das
+dazugehörige Zahlensystem _Binärsystem_. Zahlensysteme legen fest, wie Zahlen
+dargestellt werden — der Name verrät dabei jeweils, wie viele Ziffern zur
+Verfügung stehen. Um Verwechslungen zu vermeiden, können Zahlen mit einem nach-
+und tiefgestellten Index versehen werden (2 = Binärsystem, 8 = Oktalsystem, 10 =
Dezimalsystem, 16 = Hexadezimalsystem).
@@ -33,8 +32,8 @@ Dezimalsystem, 16 = Hexadezimalsystem).
:::info
-Das höchstwertige Bit wird als _Most Significant Bit_ (MSB), das niedrigstwertie
-Bit als _Least Significant Bit_ (LSB) bezeichnet.
+Das höchstwertige Bit wird als _Most Significant Bit_ (MSB), das
+niedrigstwertige Bit als _Least Significant Bit_ (LSB) bezeichnet.
:::
@@ -86,9 +85,9 @@ Notation bezeichnet wird, werden Zahlen als Produkt aus Mantisse und einer
## Größeneinheiten
-Werden 8 Bits zu einer Einheit zusammengefasst, spricht man von einem _Byte_.
-Werden 1.024 Byte wiederum zusammengefasst, spricht man von einem Kilobyte (KB)
-bei 1.024 Kilobyte von einem Megabyte (MB) und so weiter.
+Werden 8 Bits zu einer Einheit zusammengefasst, spricht man von einem _Byte_. Je
+1.024 Bytes werden wiederum zu einem Kilobyte (KB) zusammengefasst, 1.024
+Kilobyte ergeben ein Megabyte (MB) und so weiter.
| Einheit | Abkürzung | Größe in Byte | Größe in Bit |
| -------- | --------- | ----------------- | -------------- |
@@ -101,16 +100,15 @@ bei 1.024 Kilobyte von einem Megabyte (MB) und so weiter.
## Negative Binärzahlen
-Da Binärzahlen keine Vorzeichen kennen, wird zur Darstellung von negativen
-Binärzahlen ein Bit (in der Regel das MSB) als Vorzeichen genutzt, wobei die 0
-für eine positive Zahl, die 1 für eine negative Zahl steht. Verwendet man für
-die Darstellung negativer Binärzahlen lediglich das Vorzeichenbit ergeben sich
-allerdings Probleme wie eine doppelte Null sowie komplexe und ineffiziente
-Rechenoperationen. Auch beim Einerkomplement (auch b-1-Komplement), bei dem alle
-Bits der Binärzahl invertiert werden, bleiben diese Probleme (teils) bestehen.
-Daher wird zu Darstellung negativer Dezimalzahlen das sogenannte
-Zweierkomplement (auch b-Komplement) verwendet, bei welchem nach dem Invertieren
-noch eine 1 hinzuaddiert wird.
+Da Binärzahlen keine Vorzeichen kennen, wird zur Darstellung negativer Zahlen
+ein Bit (in der Regel das MSB) als Vorzeichenbit genutzt: Die 0 steht für eine
+positive, die 1 für eine negative Zahl. Verwendet man ausschließlich das
+Vorzeichenbit, entstehen jedoch Probleme wie eine doppelte Null sowie komplexe
+und ineffiziente Rechenoperationen. Auch beim _Einerkomplement_
+(b-1-Komplement), bei dem alle Bits invertiert werden, bleiben diese Probleme
+teilweise bestehen. Daher wird in der Praxis das _Zweierkomplement_
+(b-Komplement) verwendet: Nach dem Invertieren aller Bits wird zusätzlich eine 1
+addiert.
Im Beispiel wird die Zahl -5910 als negative Binärzahl dargestellt.
@@ -123,8 +121,8 @@ Im Beispiel wird die Zahl -5910 als negative Binärzahl dargestellt.
## Reelle Binärzahlen
-Die Darstellung reeller Binärzahlen erfolgt in Form von Gleitkommazahlen
-(Floating Point Numbers). Diese ist in der Norm IEEE754 festgelegt.
+Die Darstellung reeller Binärzahlen erfolgt als Gleitkommazahlen
+(Floating-Point-Zahlen) gemäß der Norm IEEE 754.
| | Datentyp | Größe | Vorzeichen | Exponent | Mantisse | Bias |
| -------------------- | -------- | ------ | ---------- | -------- | -------- | ---- |
@@ -140,7 +138,7 @@ Gleitkommazahlen können dabei spezielle Werte annehmen:
- NaN (Not a Number): ungültige Werte (z.B. _Unendlich - Unendlich_) werden als
NaN dargestellt
-Im Beispiel wir die Zahl -156,3910 als Gleitkommazahl dargestellt.
+Im Beispiel wird die Zahl -156,3910 als Gleitkommazahl dargestellt.
| | Vorzeichen | Exponent | Mantisse |
| -------------------- | ---------- | ----------- | ---------------------------------------------------- |
diff --git a/docs/documentation/calculations.md b/docs/documentation/calculations.md
index 9586cb1189..c3ef9ed0f6 100644
--- a/docs/documentation/calculations.md
+++ b/docs/documentation/calculations.md
@@ -5,9 +5,10 @@ sidebar_position: 70
tags: [java-api, math]
---
-Die Klasse `Math` stellt neben einigen Konstanten wie der Kreiszahl _Pi_ und der
-Eulerschen Zahl _E_ zahlreiche Methoden für mathematische Berechnungen zur
-Verfügung.
+Die Klasse `Math` aus dem Paket `java.lang` stellt neben den Konstanten
+`Math.PI` (Kreiszahl π) und `Math.E` (Eulersche Zahl) zahlreiche Methoden für
+mathematische Berechnungen bereit. Da alle Methoden statisch sind, müssen sie
+nicht instanziiert werden.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -17,12 +18,30 @@ public class MainClass {
int b = 3;
double result;
- result = Math.pow(a, b);
+ result = Math.pow(a, b); // a hoch b = 125.0
System.out.println(result);
- result = Math.sqrt(a);
+ result = Math.sqrt(a); // Quadratwurzel aus a = 2.236...
System.out.println(result);
}
}
```
+
+Die folgende Tabelle zeigt häufig verwendete Methoden der Klasse `Math`.
+
+| Methode | Rückgabetyp | Beschreibung |
+| -------------------------------- | ----------- | ------------------------------------------ |
+| `abs(a: int)` | `int` | Gibt den Absolutbetrag zurück |
+| `max(a: int, b: int)` | `int` | Gibt den größeren der beiden Werte zurück |
+| `min(a: int, b: int)` | `int` | Gibt den kleineren der beiden Werte zurück |
+| `pow(base: double, exp: double)` | `double` | Berechnet base hoch exp |
+| `sqrt(a: double)` | `double` | Berechnet die Quadratwurzel |
+| `round(a: double)` | `long` | Rundet auf die nächste ganze Zahl |
+| `floor(a: double)` | `double` | Rundet ab (in Richtung −∞) |
+| `ceil(a: double)` | `double` | Rundet auf (in Richtung +∞) |
+| `log(a: double)` | `double` | Berechnet den natürlichen Logarithmus |
+| `log10(a: double)` | `double` | Berechnet den dekadischen Logarithmus |
+| `sin(a: double)` | `double` | Berechnet den Sinus (Winkel in Bogenmaß) |
+| `cos(a: double)` | `double` | Berechnet den Kosinus (Winkel in Bogenmaß) |
+| `tan(a: double)` | `double` | Berechnet den Tangens (Winkel in Bogenmaß) |
diff --git a/docs/documentation/cases.md b/docs/documentation/cases.md
index 8080c2bc70..155b08b90b 100644
--- a/docs/documentation/cases.md
+++ b/docs/documentation/cases.md
@@ -5,18 +5,17 @@ sidebar_position: 95
tags: [control-structures, cases]
---
-Mit Hilfe von Verzweigungen (auch _Bedingte Anweisungen_ genannt) und
-Fallunterscheidungen können unterschiedliche Anweisungsblöcke ausgeführt werden.
-Verzweigungen und Fallunterscheidungen sind - genau wie Schleifen - wesentliche
-Bestandteile der Programmierung un werden auch als _Kontrollstrukturen_
-bezeichnet.
+Mit Hilfe von Verzweigungen (auch _bedingte Anweisungen_ genannt) und
+Fallunterscheidungen können unterschiedliche Anweisungsblöcke abhängig von
+Bedingungen ausgeführt werden. Verzweigungen und Fallunterscheidungen sind —
+genau wie Schleifen — wesentliche Bestandteile der Programmierung und werden
+zusammenfassend als _Kontrollstrukturen_ bezeichnet.
## Einfache Verzweigungen
-Die if-Verzweigung ist eine Anweisung, die abhängig von einer Bedingung zwischen
-unterschiedlichen Anweisungsblöcken auswählt: Ist die Bedingung wahr, wird der
-Anweisungsblock direkt nach der Bedingung ausgeführt, ansonsten wird der
-Anweisungsblock nach `else` ausgeführt.
+Die if-Verzweigung wählt abhängig von einer Bedingung zwischen zwei
+Anweisungsblöcken: Ist die Bedingung wahr, wird der Anweisungsblock direkt nach
+der Bedingung ausgeführt, andernfalls der Anweisungsblock nach `else`.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -44,9 +43,8 @@ Der else-Zweig ist optional, kann also weggelassen werden.
## Mehrfachverzweigungen
-Mehrfachverzweigungen können mit Hilfe einer if-else-if-Leiter abgebildet
-werden. Die if-else-if-Leiter verschachtelt mehrere if-Anweisungen zu einer
-sogenannten kaskadierten Verzweigung.
+Mehrfachverzweigungen werden mit einer if-else-if-Leiter abgebildet, die mehrere
+if-Anweisungen zu einer kaskadierten Verzweigung zusammenfasst.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -72,9 +70,9 @@ public class MainClass {
## Bedingte Zuweisungen
-Wird eine if-Verzweigung für eine Wertzuweisung verwendet, spricht man von einer
-bedingten Zuweisung. Zusätzlich zur ausführlichen Schreibweise existiert für
-bedingte Zuweisungen auch eine Kurzschreibweise.
+Wird eine if-Verzweigung ausschließlich für eine Wertzuweisung verwendet,
+spricht man von einer bedingten Zuweisung. Neben der ausführlichen Schreibweise
+gibt es dafür auch eine kompakte Kurzschreibweise mit dem Ternäroperator `?:`.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -84,7 +82,7 @@ public class MainClass {
int y = 2;
int z;
- /* ausführliche Schreibweise */
+ // ausführliche Schreibweise
if (x > y) {
z = 3;
} else {
@@ -92,7 +90,7 @@ public class MainClass {
}
System.out.println(z);
- /* Kurzschreibweise */
+ // Kurzschreibweise mit dem Ternäroperator
z = (x > y) ? 3 : 4;
System.out.println(z);
}
@@ -109,11 +107,11 @@ Lesbarkeit dadurch eventuell erschwert wird.
## Fallunterscheidungen
-Fallunterscheidungen können entweder mit Hilfe von if-else-if-Leitern oder mit
-Hilfe der switch-case-Anweisung realisiert werden. Tritt ein Fall ein, werden
-alle Anweisungen bis zum nächsten `break` ausgeführt. Durch Weglassen von
-`break` können unterschiedliche Fälle gleich behandelt werden. Der default-Block
-wird immer dann ausgeführt, wenn keiner der aufgeführten Fälle eintritt.
+Fallunterscheidungen können entweder mit einer if-else-if-Leiter oder mit der
+switch-case-Anweisung umgesetzt werden. Tritt ein Fall ein, werden alle
+Anweisungen bis zum nächsten `break` ausgeführt. Durch das Weglassen von `break`
+können mehrere Fälle gleich behandelt werden. Der `default`-Block wird
+ausgeführt, wenn keiner der aufgeführten Fälle zutrifft.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -141,8 +139,8 @@ public class MainClass {
}
```
-Seit Java 14 beheben Switch-Ausdrücke einige Ungereimtheiten der klassischen
-switch-case-Anweisung und ermöglichen eine elegantere Syntax.
+Seit Java 14 vereinfachen Switch-Ausdrücke die Syntax und beheben einige
+Schwächen der klassischen switch-case-Anweisung.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/class-structure.mdx b/docs/documentation/class-structure.mdx
index ed65c8bea9..2f5b17c459 100644
--- a/docs/documentation/class-structure.mdx
+++ b/docs/documentation/class-structure.mdx
@@ -9,13 +9,13 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Klassen stellen den grundlegenden Rahmen für Programme dar. Jede Klasse kann
-Daten (_Attribute_) und Routinen (_Methoden_) besitzen. Routinen bestehen dabei
-aus Folgen von verzweigten und sich wiederholenden Anweisungen, wobei
-Anweisungen wohldefinierte Befehle darstellen, die der Interpreter zur Laufzeit
-ausführt. Anweisungen müssen in Java mit dem Semikolon abgeschlossen werden und
-können zu Anweisungsblöcken zusammengefasst werden, die durch geschweifte
-Klammern umschlossen werden. Innerhalb eines Anweisungsblocks können sich
-weitere Anweisungsblöcke befinden.
+Daten (_Attribute_) und Routinen (_Methoden_) besitzen. Routinen bestehen aus
+Folgen von verzweigten und sich wiederholenden Anweisungen, wobei Anweisungen
+wohldefinierte Befehle darstellen, die der Interpreter zur Laufzeit ausführt.
+Anweisungen müssen in Java mit einem Semikolon abgeschlossen werden und können
+zu Anweisungsblöcken zusammengefasst werden, die durch geschweifte Klammern
+umschlossen sind. Innerhalb eines Anweisungsblocks können weitere
+Anweisungsblöcke enthalten sein.
@@ -70,7 +70,7 @@ public class MainClass {
Statische Methoden sind abgeschlossene Programmteile, die Parameter enthalten
und einen Wert zurückgeben können. Sie müssen mit dem Schlüsselwort `static`
gekennzeichnet werden. Bei statischen Methoden, die einen Wert zurückgeben, muss
-der Datentyp des Rückgabewertes angegeben werden; bei statische Methoden, die
+der Datentyp des Rückgabewerts angegeben werden; bei statischen Methoden, die
keinen Wert zurückgeben, das Schlüsselwort `void`. Der Aufruf einer statischen
Methode erfolgt über den Klassennamen gefolgt von einem Punkt.
diff --git a/docs/documentation/classes.md b/docs/documentation/classes.md
index 9d38ab1a61..e8b78c4ec7 100644
--- a/docs/documentation/classes.md
+++ b/docs/documentation/classes.md
@@ -5,14 +5,13 @@ sidebar_position: 131
tags: [oo]
---
-Klassen legen die Eigenschafen (Attribute) sowie das Verhalten (Methoden) von
-Objekten fest und stellen damit quasi Baupläne für Objekte dar.
+Klassen legen die Eigenschaften (Attribute) sowie das Verhalten (Methoden) von
+Objekten fest und stellen damit Baupläne für Objekte dar.
## Sichtbarkeit von Klassen, Attributen und Methoden
-Um die Sichtbarkeit von Klassen, Attributen und Methoden zu definieren,
-existieren verschiedene Zugriffsrechte. Die Sichtbarkeit bestimmt, von welchem
-Ort aus Klassen, Attribute und Methoden verwendet bzw. aufgerufen werden dürfen.
+Über _Zugriffsrechte_ wird festgelegt, von welchem Ort aus auf Klassen,
+Attribute und Methoden zugegriffen werden darf.
| Zugriffsrecht | Zugriff aus gleicher Klasse | Zugriff von einer Klasse aus dem gleichen Paket | Zugriff von einer Unterklasse | Zugriff von einer beliebigen Klasse |
| ------------- | --------------------------- | ----------------------------------------------- | ----------------------------- | ----------------------------------- |
@@ -23,11 +22,11 @@ Ort aus Klassen, Attribute und Methoden verwendet bzw. aufgerufen werden dürfen
## Definition von Attributen
-Die Attribute einer Klasse sind Datenobjekte und werdern daher analog zu
-Variablen und Konstanten definiert. Das Schlüsselwort `final` erlaubt die
-Definition von unveränderlichen Attributen, also Attributen, deren Wert nicht
-geändert werden kann. Die Initialisierung dieser unveränderlichen Attribute
-erfolgt durch [Konstruktoren](classes#definition-von-konstruktoren).
+Die Attribute einer Klasse sind Datenobjekte und werden daher analog zu
+Variablen und Konstanten definiert. Mit dem Schlüsselwort `final` lassen sich
+unveränderliche Attribute definieren, deren Wert nach der Initialisierung nicht
+mehr geändert werden kann. Die Initialisierung dieser Attribute erfolgt im
+[Konstruktor](classes#definition-von-konstruktoren).
```java title="Computer.java (Auszug)" showLineNumbers
public class Computer {
@@ -48,17 +47,16 @@ Die Selbstreferenz `this` verweist innerhalb einer Klasse auf das eigene Objekt
## Definition und Implementierung von Methoden
-Methoden sind in der Programmierung eine Verallgemeinerung von mathematischen
-Funktionen. Eine Methode besteht aus einem Methodennamen, einer Liste von
-Eingabeparameter (optional), einem Rückgabewert (optional) sowie dem
-Methodenrumpf. Die Kombination aus Methodenname und den Datentypen der
-Parameterliste bezeichent man als _Signatur einer Methode_.
+Methoden sind in der Programmierung eine Verallgemeinerung mathematischer
+Funktionen. Eine Methode besteht aus einem Namen, einer (optionalen) Liste von
+Eingabeparametern, einem (optionalen) Rückgabewert sowie dem Methodenrumpf. Die
+Kombination aus Methodenname und den Datentypen der Parameterliste bezeichnet
+man als _Signatur_.
-Methoden können entweder genau einen Rückgabewert oder keinen Rückgabewert
-besitzen. Methoden mit genau einem Rückgabewert müssen vor dem Methodennamen den
-Datentyp des Rückgabewerts angeben und am Ende des Methodenrumpfes immer die
-Anweisung `return` besitzen, Methoden ohne Rückgabewert müssen dies mit dem
-Schlüsselwort `void` kenntlich machen.
+Methoden können entweder genau einen Rückgabewert oder keinen besitzen. Methoden
+mit einem Rückgabewert müssen vor dem Methodennamen den Rückgabetyp angeben und
+im Methodenrumpf eine `return`-Anweisung enthalten. Methoden ohne Rückgabewert
+werden mit `void` gekennzeichnet.
```java title="Computer.java (Auszug)" showLineNumbers
public class Computer {
@@ -88,10 +86,10 @@ public class Computer {
## Definition überladener Methoden
-Gleichnamige Methoden mit unterschiedlichen Parameterlisten einer Klasse werden
-als überladene Methoden bezeichnet. Man spricht in diesem Zusammenhang auch von
-statischer Polymorphie, da der Aufruf gleichnamiger Methoden unterschiedliche
-Ergebnisse liefern kann.
+Gleichnamige Methoden mit unterschiedlichen Parameterlisten in einer Klasse
+werden als _überladene Methoden_ bezeichnet. Dieses Konzept nennt man auch
+_statische Polymorphie_, da der Aufruf gleichnamiger Methoden je nach Parametern
+zu unterschiedlichen Ergebnissen führt.
```java title="Computer.java (Auszug)" showLineNumbers
public class Computer {
@@ -115,17 +113,14 @@ public class Computer {
## Definition von Konstruktoren
-Bei Konstruktoren handelt es sich um spezielle Methoden, die zur Initialisierung
-eines Objekts verwendet werden. Konstruktoren heißen wie ihre Klasse und können
-eine beliebige Anzahl an Parametern haben. Allerdings kann für Konstruktoren
-kein Rückgabewert festgelegt werden, da diese implizit die Referenz auf das
-Objekt zurückgeben.
+Konstruktoren sind spezielle Methoden, die zur Initialisierung eines Objekts
+dienen. Sie tragen denselben Namen wie ihre Klasse und können beliebig viele
+Parameter haben. Ein Rückgabetyp wird nicht angegeben, da Konstruktoren implizit
+eine Referenz auf das neue Objekt zurückgeben.
-Im Gegensatz zu z.B. C++ existieren in Java keine Destruktoren, die nicht mehr
-benötigte Objekte aus dem Speicher entfernen. Stattdessen läuft im Hintergrund
-der sogenannte Garbage Collector, der nicht mehr benötigte Objekte (also
-Objekte, die nicht mehr über eine Referenzvariable angesprochen werden können)
-löscht.
+Im Gegensatz zu z.B. C++ gibt es in Java keine Destruktoren. Stattdessen
+übernimmt der _Garbage Collector_ im Hintergrund das Aufräumen: Er entfernt
+Objekte aus dem Speicher, auf die keine Referenzvariable mehr zeigt.
```java title="Computer.java (Auszug)" showLineNumbers
public class Computer {
@@ -145,24 +140,22 @@ public class Computer {
:::info
-Auch Konstruktoren können überladen werden, das heißt eine Klasse kann über
-mehrere Konstruktoren verfügen. Der Aufruf eines Konstruktors innerhalb eines
-anderen Konstruktors erfolgt dabei über die Selbstreferenz `this`.
+Auch Konstruktoren können überladen werden, d.h. eine Klasse kann über mehrere
+Konstruktoren verfügen. Ein Konstruktor kann dabei einen anderen Konstruktor
+derselben Klasse mit `this(...)` aufrufen.
:::
## Definition statischer Attribute und Methoden
-Neben "normalen" Attributen und Methoden kann eine Klasse auch statische
-Attribute und statische Methoden besitzen. Im Gegensatz zu "normalen" Attributen
-existieren statische Attribute nur einmal pro Klasse und besitzen daher für alle
-Objekte dieser Klasse dieselben Werte. Innerhalb einer statischen Methode kann
-nur auf die statischen Attribute der Klasse zugegriffen werden.
+Neben Instanzattributen und -methoden kann eine Klasse auch statische Attribute
+und Methoden besitzen. Statische Attribute existieren nur einmal pro Klasse und
+haben für alle Objekte dieser Klasse denselben Wert. Innerhalb einer statischen
+Methode kann nur auf statische Attribute zugegriffen werden.
-Bei der Deklaration von statischen Attributen und statischen Methoden kommt das
-Schlüsselwort `static` zum Einsatz. Für den Zugriff auf ein statisches Attribut
-bzw. den Aufruf einer statischen Methode wird keine Instanziierung benötigt,
-d.h. der der Zugriff bzw. Aufruf erfolgt über den Klassennamen.
+Statische Attribute und Methoden werden mit dem Schlüsselwort `static`
+deklariert. Für den Zugriff ist keine Instanziierung nötig — er erfolgt direkt
+über den Klassennamen.
```java title="Computer.java (Auszug)" showLineNumbers
public class Computer {
@@ -183,8 +176,7 @@ public class Computer {
:::info
-"Normale" Attribute und Methoden werden auch als Instanzattribute bzw.
-Instanzmethoden bezeichnet, statische Attribute und Methoden auch
-Klassenattribute bzw. Klassenmethoden.
+Instanzattribute und -methoden werden auch als Klassenattribute und
+Klassenmethoden bezeichnet, wenn sie statisch sind.
:::
diff --git a/docs/documentation/coding.mdx b/docs/documentation/coding.mdx
index 5608e90a16..6597d880dd 100644
--- a/docs/documentation/coding.mdx
+++ b/docs/documentation/coding.mdx
@@ -9,9 +9,9 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Als ein Teilbereich der Softwareentwicklung umfasst das Programmieren vor allem
-die Umsetzung eines Softwareentwurfes in Quellcode. Generell versteht man unter
+die Umsetzung eines Softwareentwurfs in Quellcode. Allgemein versteht man unter
Programmieren die Umsetzung von [Algorithmen](algorithms) in lauffähige
-Computer-Programme.
+Programme.
```mermaid
flowchart LR
@@ -26,38 +26,36 @@ Ein Algorithmus ist eine Handlungsvorschrift zur Lösung eines Problems.
## Abstraktionsniveau
-Maschinen sind im Vergleich zu menschlichen Gehirnen sehr primitive Gebilde. Die
+Maschinen sind im Vergleich zum menschlichen Gehirn sehr primitive Gebilde. Die
Diskrepanz zwischen der menschlichen Denkweise und der Arbeitsweise von
-Maschinen bezeichnet mal als _Semantische Lücke_. Programmiersprachen
+Maschinen bezeichnet man als _Semantische Lücke_. Programmiersprachen
ermöglichen es, Problemstellungen der realen Welt abstrahiert und
-maschinengerecht abzubilden und damit die Semantische Lücke zu verringern. Je
-höher die Abstraktion einer Programmiersprache dabei ist, desto mehr kann die
-Semantische Lücke verringert werden: Maschinenorientierte Programmiersprachen
-(z.B. X86-Assembler) abstrahieren kaum und sind daher für den Menschen schwerer
-verständlich, problemorientierte Programmiersprachen (z.B. Java) abstrahieren
-stark und sind daher für den Menschen leichter verständlich.
-
-| | Generation | Merkmale | Sprachen |
-| ---------------- | ------------------------------ | ------------------------------------------ | ------------------------------------------- |
-| Höhere Sprachen | 5: Sprachen der KI | Logik- und Regelbasiert | Lisp, Prolog |
-| Höhere Sprachen | 4: Anwendungsbezogene Sprachen | Domänenspezifisch | SQL |
-| Höhere Sprachen | 3: Problemorientierte Sprachen | Datenobjekte, Routinen, Kontrollstrukturen | C, C++, C#, Java, JavaScript, Python |
-| Niedere Sprachen | 2: Assemblersprachen | Symbolische Befehle | X86-Assembler, MIPS-Asembler, ARM-Assembler |
-| Niedere Sprachen | 1: Maschinensprache | Binärcode | - |
+maschinengerecht abzubilden und damit diese Lücke zu verringern. Je höher die
+Abstraktion einer Programmiersprache ist, desto mehr lässt sich die Semantische
+Lücke verringern: Maschinenorientierte Sprachen (z.B. x86-Assembler)
+abstrahieren kaum und sind daher für den Menschen schwerer verständlich,
+problemorientierte Sprachen (z.B. Java) abstrahieren stark und sind daher
+deutlich leichter verständlich.
+
+| | Generation | Merkmale | Sprachen |
+| ---------------- | ------------------------------ | ------------------------------------------ | -------------------------------------------- |
+| Höhere Sprachen | 5: Sprachen der KI | Logik- und Regelbasiert | Lisp, Prolog |
+| Höhere Sprachen | 4: Anwendungsbezogene Sprachen | Domänenspezifisch | SQL |
+| Höhere Sprachen | 3: Problemorientierte Sprachen | Datenobjekte, Routinen, Kontrollstrukturen | C, C++, C#, Java, JavaScript, Python |
+| Niedere Sprachen | 2: Assemblersprachen | Symbolische Befehle | X86-Assembler, MIPS-Assembler, ARM-Assembler |
+| Niedere Sprachen | 1: Maschinensprache | Binärcode | - |
## Programmierparadigmen
Unter einem Programmierparadigma versteht man die grundlegende Herangehensweise,
-Probleme mit Hilfe einer Programmiersprache zu lösen. Aber auch wenn
-Programmiersprachen oft anhand ihrer grundlegenden Merkmale genau einem
-Programmierparadigma zugeordnet werden, unterstützen viele Programmiersprachen
-mehrere Programmierparadigmen. Generell werden die verschiedenen
-Programmierparadigmen oft in zwei große Kategorien eingeteilt: bei imperativen
-Programmierparadigmen steht die Frage _Wie soll das Ergebnis erreicht werden?_
-im Vordergrund, bei deklarativen Programmierparadigmen die Frage _Was soll das
-Ergebnis sein?_. Imperative Programmierparadigmen legen also Schritt für Schritt
-fest, wie das Ergebnis erreicht werden soll, deklarative Programmierparadigmen
-beschreiben das Ergebnis selbst.
+Probleme mit Hilfe einer Programmiersprache zu lösen. Viele Programmiersprachen
+unterstützen dabei mehrere Paradigmen gleichzeitig, auch wenn sie oft einem
+bestimmten Paradigma zugeordnet werden. Generell werden Programmierparadigmen in
+zwei große Kategorien eingeteilt: Bei _imperativen_ Paradigmen steht die Frage
+_Wie soll das Ergebnis erreicht werden?_ im Vordergrund, bei _deklarativen_
+Paradigmen die Frage _Was soll das Ergebnis sein?_ Imperative Paradigmen legen
+also Schritt für Schritt fest, wie ein Ergebnis erreicht wird; deklarative
+Paradigmen beschreiben stattdessen das gewünschte Ergebnis.
| Programmierparadigmen | Kategorie | Fokus | Beispielsprachen |
| -------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
@@ -68,17 +66,16 @@ beschreiben das Ergebnis selbst.
## Programmausführung
-Programme auf einem Computer können auf unterschiedliche Arten ausgeführt
-werden: Compilersprachen übersetzen den Quellcode in eine Datei, die vom
-jeweiligen Betriebssystem ausgeführt werden kann, Interpretersprachen übersetzen
-den Quellcode direkt in den Arbeitsspeicher und führen das Programm sofort aus
-und Just-In-Time Compilersprachen (JIT) übersetzen den Quellcode mit Hilfe eines
-Compilers zunächst in den sogenannten Bytecode und übersetzen diesen bei der
-Ausführung in den Arbeitsspeicher. Compilersprachen wie C und C++ sind dabei
-deutlich performanter und ermöglichen eine sicherere Entwicklung,
-Interpretersprachen wie JavaScript und Python sind dagegen plattformunabhängig
-und Just-In-Time Compliersprachen wie C# und Java vereinen die Vorteile beider
-Welten.
+Programme können auf einem Computer auf unterschiedliche Arten ausgeführt
+werden. Bei _Compilersprachen_ wird der Quellcode vor der Ausführung vollständig
+in eine ausführbare Datei übersetzt. Bei _Interpretersprachen_ wird der
+Quellcode zur Laufzeit direkt ausgeführt, ohne vorherige Übersetzung.
+_Just-In-Time- Compilersprachen_ (JIT) kombinieren beide Ansätze: Der Quellcode
+wird zunächst in einen plattformunabhängigen Bytecode kompiliert, der dann zur
+Laufzeit ausgeführt wird. Compilersprachen wie C und C++ sind dabei besonders
+performant, Interpretersprachen wie JavaScript und Python sind
+plattformunabhängig und JIT-Sprachen wie C# und Java vereinen die Vorteile
+beider Ansätze.
diff --git a/docs/documentation/comparators.md b/docs/documentation/comparators.md
index 4dcbde1592..0a1faa4b79 100644
--- a/docs/documentation/comparators.md
+++ b/docs/documentation/comparators.md
@@ -5,14 +5,14 @@ sidebar_position: 220
tags: [comparators]
---
-Mit Hilfe der Methode `int compareTo(o: T)` der Schnittstelle `Comparable`
-bzw. der Methode `int compare(o1: T, o2: T)` der Schnittstelle `Comparator`
-können Objekte einer Klasse miteinander verglichen werden. Der Rückgabewert
-beider Methoden gibt die Ordnung der zu vergleichenden Objekte an:
+Mit der Methode `int compareTo(o: T)` der Schnittstelle `Comparable` bzw. der
+Methode `int compare(o1: T, o2: T)` der Schnittstelle `Comparator` lassen
+sich Objekte miteinander vergleichen. Der Rückgabewert gibt die relative Ordnung
+der verglichenen Objekte an:
-- Rückgabewert kleiner Null: das Vergleichsobjekt ist größer
-- Rückgabewert gleich Null: beide Objekte sind gleich groß
-- Rückgabewert größer Null: das Vergleichsobjekt ist kleiner
+- Rückgabewert < 0: das erste Objekt ist kleiner als das zweite
+- Rückgabewert = 0: beide Objekte sind gleichwertig
+- Rückgabewert > 0: das erste Objekt ist größer als das zweite
Objekte der Klasse `Notebook` können durch die Implementierung der Methode
`int compareTo(o: T)` der Schnittstelle `Comparable` miteinander verglichen
@@ -43,11 +43,10 @@ public class NotebookByPowerInGhzComparator implements Comparator {
}
```
-In der main-Methode der Startklasse wird mit Hilfe der statischen Methode
-`void sort(list: List)` der Klasse `Collections` eine Liste mit Objekten der
-Klasse `Notebook` sortiert. Aufgrund der Implementierung der compareTo-Methode
-wird die Liste zunächst absteigend nach dem Attribut `memoryInGb` sortiert.
-Anschließend wird die Liste aufsteigend nach der Prozessorleistung sortiert.
+In der main-Methode wird mit der statischen Methode `void sort(list: List)`
+der Klasse `Collections` eine Liste von `Notebook`-Objekten sortiert. Zunächst
+wird nach `memoryInGb` absteigend sortiert (gemäß `compareTo`), anschließend
+nach Prozessorleistung aufsteigend (gemäß `NotebookByPowerInGhzComparator`).
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/console-applications.md b/docs/documentation/console-applications.md
index 4fe952dda8..2a5ec8f808 100644
--- a/docs/documentation/console-applications.md
+++ b/docs/documentation/console-applications.md
@@ -5,9 +5,9 @@ sidebar_position: 90
tags: [console-applications]
---
-Konsolenanwendungen sind Programme ohne eine grafische Benutzeroberfläche d.h.
-die Steuerung sowie die Eingabe und Ausgabe erfolgen ausschließlich über
-textuelle Anweisungen.
+Konsolenanwendungen sind Programme ohne grafische Benutzeroberfläche. Die
+Steuerung sowie die Ein- und Ausgabe erfolgen ausschließlich über textuelle
+Anweisungen.
```mermaid
flowchart
@@ -17,25 +17,35 @@ flowchart
## Konsoleneingaben
-Die Klasse `Scanner` im Paket `java.util` stellt Methoden zur Verfügung, um
-Eingaben von der Konsole einzulesen und in entsprechende Datentypen umzuwandeln.
+Die Klasse `Scanner` im Paket `java.util` stellt Methoden bereit, um Eingaben
+von der Konsole einzulesen und in entsprechende Datentypen umzuwandeln. Dem
+Konstruktor muss dazu der Standard-Eingabestrom `System.in` übergeben werden.
```java title="MainClass.java" showLineNumbers
public class MainClass {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
- int i = scanner.nextInt();
+ int i = scanner.nextInt(); // ganze Zahl einlesen
System.out.println(i);
}
}
```
+Die folgende Tabelle zeigt häufig verwendete Methoden der Klasse `Scanner`.
+
+| Methode | Rückgabetyp | Beschreibung |
+| --------------- | ----------- | ------------------------------------------------ |
+| `nextInt()` | `int` | Liest die nächste ganze Zahl ein |
+| `nextDouble()` | `double` | Liest die nächste Dezimalzahl ein |
+| `nextBoolean()` | `boolean` | Liest den nächsten booleschen Wert ein |
+| `next()` | `String` | Liest das nächste Wort ein (bis zum Leerzeichen) |
+| `nextLine()` | `String` | Liest die nächste Zeile ein |
+
:::info
-Dem Konstruktor muss der Standard-Eingabestrom `System.in` als Wert mitgegeben
-werden.
+Dem Konstruktor muss der Standard-Eingabestrom `System.in` übergeben werden.
:::
@@ -44,13 +54,10 @@ werden.
Der Standard-Ausgabestrom `System.out` bietet verschiedene Methoden, um
Informationen auf der Konsole auszugeben:
-- Bei den print-Methoden wird die Information unverändert und linksbündig
- ausgegeben
-- Bei den println-Methoden wird die Information unverändert und linksbündig
- ausgegeben. Zusätzlich wird ein Zeilenumbruch ausgeführt
-- Bei den printf-Methoden wird die Information formatiert ausgegeben. Die
- Formatierungsregeln sind nach dem Muster
- _[flags]\[width][.precision]conversion-character_ aufgebaut
+- `print()` — gibt den Text ohne Zeilenumbruch aus
+- `println()` — gibt den Text aus und fügt einen Zeilenumbruch an
+- `printf()` — gibt den Text formatiert aus; die Formatierungsregeln folgen dem
+ Muster `[flags][width][.precision]conversion-character`
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/data-objects.md b/docs/documentation/data-objects.md
index ea4c4ef28e..80da16846b 100644
--- a/docs/documentation/data-objects.md
+++ b/docs/documentation/data-objects.md
@@ -5,16 +5,15 @@ sidebar_position: 40
tags: [data-objects]
---
-Ein Datenobjekt ist ein Platzhalter, der zur Laufzeit eine bestimmte Stelle des
-Arbeitsspeichers belegt. Die Größe des reservierten Speichers ist abhängig vom
-gewählten [Datentyp](data-types)). Datenobjekte können mit Werten belegt werden,
-Bezeichner ermöglichen das Ansprechen im Programmablauf. Man unterscheidet
+Ein Datenobjekt ist ein Platzhalter, der zur Laufzeit eine bestimmte Stelle im
+Arbeitsspeicher belegt. Die Größe des reservierten Speichers hängt vom gewählten
+[Datentyp](data-types) ab. Datenobjekte können mit Werten belegt werden;
+Bezeichner ermöglichen es, sie im Programmablauf anzusprechen. Man unterscheidet
zwischen variablen Datenobjekten (_Variablen_) und fixen Datenobjekten
-(_Konstanten_ und _Literale_). Konstanten sind fixe Datenobjekte, die über einen
-Bezeichner angesprochen werden können. Sie werden mit dem Schlüsselwort `final`
-deklariert. Literale sind sogenannte wörtliche Konstanten, d.h. fixe
-Datenobjekte ohne Bezeichner. Da Literale über keinen Bezeichner verfügen,
-können Sie im Programm nicht angesprochen werden.
+(_Konstanten_ und _Literale_). Konstanten sind fixe Datenobjekte mit einem
+Bezeichner und werden mit dem Schlüsselwort `final` deklariert. Literale sind
+sogenannte wörtliche Konstanten — also fixe Datenobjekte ohne Bezeichner, auf
+die daher im Programmcode nicht zugegriffen werden kann.
```mermaid
flowchart
@@ -31,10 +30,10 @@ flowchart
## Deklaration von Datenobjekten
-Durch Angabe von Datentyp und Bezeichner wird ein Datenobjekt deklariert, d.h.
-dem Compiler bekannt gegeben. Deklarationen werden wie jede Anweisung mit einem
-Semikolon abgeschlossen. Datenobjekte gleichen Datentyps können mit Komma
-getrennt aufgeführt werden.
+Durch die Angabe von Datentyp und Bezeichner wird ein Datenobjekt deklariert,
+d.h. dem Compiler bekannt gemacht. Deklarationen werden wie jede Anweisung mit
+einem Semikolon abgeschlossen. Mehrere Datenobjekte desselben Datentyps können
+kommagetrennt in einer Zeile deklariert werden.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -51,17 +50,17 @@ public class MainClass {
:::info
-Java ist case-sensitiv, unterscheidet also zwischen Groß- und Kleinschreibung.
-Um die Lesbarkeit zu erhöhen, sollten Variablen mit einem Kleinbuchstaben
-beginnen, wohingegen Konstanten immer in Großbuchstaben geschrieben werden
-sollten.
+Java ist case-sensitiv und unterscheidet also zwischen Groß- und
+Kleinschreibung. Zur besseren Lesbarkeit sollten Variablen mit einem
+Kleinbuchstaben beginnen, Konstanten hingegen vollständig in Großbuchstaben
+geschrieben werden.
:::
## Initialisierung von Datenobjekten
-In Java müssen Datenobjekte vor der ersten Verwendung explizit initialisiert
-werden, d.h. mit einem Wert belegt werden. Der Zuweisungsoperator `=` weist dem
+In Java müssen Datenobjekte vor ihrer ersten Verwendung explizit initialisiert,
+d.h. mit einem Wert belegt werden. Der Zuweisungsoperator `=` weist dem
Datenobjekt auf der linken Seite den Wert des Ausdrucks auf der rechten Seite
zu.
@@ -83,10 +82,10 @@ public class MainClass {
## Typinferenz bei Datenobjekten
-Unter Typinferenz versteht man, dass bei der Deklaration eines Datenobjekts auf
-die Angabe eine Datentyps verzichtet werden kann, wenn der Compiler aufgrund der
-restlichen Angaben den Typ selbstständig ermitteln kann. Für die Typinferenz
-wird das Schlüsselwort `var` verwendet.
+Unter _Typinferenz_ versteht man, dass bei der Deklaration eines Datenobjekts
+auf die explizite Angabe eines Datentyps verzichtet werden kann, wenn der
+Compiler den Typ anhand der übrigen Angaben selbstständig ermitteln kann. Für
+die Typinferenz wird das Schlüsselwort `var` verwendet.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -96,7 +95,7 @@ public class MainClass {
i = "Text"; // Kompilierungsfehler
var j = 5;
- j = "Text"; // Kompilierungsfehler
+ j = "Text"; // Kompilierungsfehler: j ist statisch als int typisiert
}
}
@@ -110,8 +109,9 @@ Mit `var` deklarierte Datenobjekte sind weiterhin statisch typisiert.
## Gültigkeitsbereiche von Datenobjekten
-Datenobjekte sind nur innerhalb eines Anweisungsblocks gültig, d.h. man kann nur
-innerhalb dieses Programmabschnitts auf das Datenobjekt zugreifen.
+Datenobjekte sind nur innerhalb des Anweisungsblocks gültig, in dem sie
+deklariert wurden. Außerhalb dieses Blocks kann nicht auf sie zugegriffen
+werden.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -123,7 +123,7 @@ public class MainClass {
public static int foo(int c) {
int d;
- d = a++; // Kompilierungsfehler
+ d = a++; // Kompilierungsfehler: a ist hier nicht sichtbar
d = c++;
return d;
}
@@ -134,9 +134,9 @@ public class MainClass {
## Typumwandlung (Type Casting)
Der Cast-Operator `()` erlaubt die explizite Umwandlung eines Datentyps in einen
-anderen. Bei Wertzuweisungen findet eine implizite Typumwandlung vom
+anderen. Bei Wertzuweisungen findet außerdem eine implizite Typumwandlung vom
niederwertigen zum höherwertigen Datentyp statt. Zu beachten ist, dass bei einer
-Typumwandlung ein Genauigkeitsverlust stattfinden kann.
+Typumwandlung ein Genauigkeitsverlust auftreten kann.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -146,11 +146,11 @@ public class MainClass {
int b = 3;
double result;
- // implizite Typumwandlung
+ // implizite Typumwandlung: Ergebnis ist 4.0, da beide Operanden int sind
result = a / b;
System.out.println(result);
- // explizite Typumwandlung
+ // explizite Typumwandlung: Ergebnis ist 4.666...
result = (double) a / b;
System.out.println(result);
}
@@ -158,8 +158,7 @@ public class MainClass {
}
```
-Die Wertigkeit von Datentypen entscheidet darüber, welche Typumwandlungen
-möglich sind.
+Die Wertigkeit der Datentypen bestimmt, welche Typumwandlungen möglich sind.
```mermaid
flowchart
diff --git a/docs/documentation/data-types.mdx b/docs/documentation/data-types.mdx
index ff6dec878d..d586b008d4 100644
--- a/docs/documentation/data-types.mdx
+++ b/docs/documentation/data-types.mdx
@@ -8,16 +8,15 @@ tags: [data-types]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Datentypen legen neben der Größe des Arbeitsspeichers, die ein Datenobjekt
-benötigt, auch die Art der Information fest, die im Datenobjekt gespeichert
-werden kann.
+Datentypen legen fest, welche Art von Information in einem Datenobjekt
+gespeichert werden kann und wie viel Arbeitsspeicher dafür reserviert wird.
Primitive Datentypen sind fest in der Programmiersprache verankert und können
-durch entsprechende Schlüsselwörter angesprochen werden. Java kennt 8 solcher
-primitiver Datentypen.
+über entsprechende Schlüsselwörter verwendet werden. Java kennt 8 primitive
+Datentypen.
| Datentyp | Größe | Wertebereich |
| -------- | ------ | --------------------------------------------------------- |
@@ -58,12 +57,12 @@ Weitere Informationen zu strukturierten Datentypen finden sich im Kapitel
Klassen, die über einen oder mehrere formale Typparameter verfügen, werden als
generische Klassen bezeichnet. Generische Klassen können mit verschiedenen
-Datentypen verwendet werden und ermöglichen dadurch die Wiederverwendung von
-Code unter Beibehaltung statischer Typsicherheit. Unter Typsicherheit versteht
-man, dass Datentypen gemäß ihrer Definition verwendet werden und dabei keine
-Typverletzungen auftreten. Bei statisch typisierten Sprachen findet die
-Typprüfung bei der Kompilierung statt. Beispiele für generische Klassen sind die
-Klasse `ArrayList` sowie die Klasse `HashMap`.
+Datentypen verwendet werden und ermöglichen so die Wiederverwendung von Code bei
+gleichzeitiger statischer Typsicherheit. Unter _Typsicherheit_ versteht man,
+dass Datentypen gemäß ihrer Definition verwendet werden und keine
+Typverletzungen auftreten. Bei statisch typisierten Sprachen erfolgt die
+Typprüfung bereits zur Kompilierzeit. Beispiele für generische Klassen sind
+`ArrayList` und `HashMap`.
:::info
@@ -75,12 +74,11 @@ Weitere Informationen zu generischen Datentypen finden sich im Kapitel
-Abstrakte Datentypen sind Sammlungen von Daten samt den dazugehörigen
-Operationen wie Einfügen, Löschen etc. Beispiele für abstrakte Datentypen sind
-Listen (z.B. die Klassen `ArrayList` und `LinkedList`), Mengen (z.B. die
-Klassen `HashSet` und `TreeSet`), Warteschlangen (z.B. die Klassen
-`LinkedList` und `PriorityQueue`) sowie Assoziativspeicher (z.B. die
-Klassen `HashMap` und `TreeMap`).
+Abstrakte Datentypen sind Sammlungen von Daten zusammen mit den dazugehörigen
+Operationen wie Einfügen oder Löschen. Beispiele für abstrakte Datentypen sind
+Listen (z.B. `ArrayList` und `LinkedList`), Mengen (z.B. `HashSet` und
+`TreeSet`), Warteschlangen (z.B. `LinkedList` und `PriorityQueue`)
+sowie Assoziativspeicher (z.B. `HashMap` und `TreeMap`).
:::info
diff --git a/docs/documentation/dates-and-times.md b/docs/documentation/dates-and-times.md
index b57aaa96f2..6837bd8dc3 100644
--- a/docs/documentation/dates-and-times.md
+++ b/docs/documentation/dates-and-times.md
@@ -5,8 +5,9 @@ sidebar_position: 142
tags: [java-api, dates-and-times]
---
-Die Klasse `LocalDateTime` liefert alle relevanten Informationen zum fast
-weltweit verwendeten Kalendersystem ISO-8601 (gregorianischer Kalender).
+Die Klasse `LocalDateTime` stellt Informationen zum gregorianischen Kalender
+(ISO-8601) bereit und gibt Zugriff auf Jahr, Monat, Tag, Stunde, Minute und
+Sekunde der aktuellen Systemzeit.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -22,9 +23,9 @@ public class MainClass {
}
```
-Neben den print-Methoden des Standard-Ausgabestroms `System.out` besitzt die
-Klasse `System` auch die Methode `long currentTimeMillis()`, die die Differenz
-in Millisekunden zwischen der aktuellen Systemzeit und dem Nullpunkt zurückgibt.
+Neben `LocalDateTime` bietet die Klasse `System` die Methode
+`long currentTimeMillis()`, die die Differenz in Millisekunden zwischen der
+aktuellen Systemzeit und dem Nullpunkt (1. Januar 1970, 0 Uhr) zurückgibt.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -39,6 +40,6 @@ public class MainClass {
:::info
-Der festgelegte Nullpunkt ist der 1. Januar 1970, 0 Uhr.
+Der Nullpunkt (Unix-Epoch) ist der 1. Januar 1970 um 0:00 Uhr UTC.
:::
diff --git a/docs/documentation/enumerations.md b/docs/documentation/enumerations.md
index 28e9b031ed..49bf9d83ab 100644
--- a/docs/documentation/enumerations.md
+++ b/docs/documentation/enumerations.md
@@ -5,16 +5,15 @@ sidebar_position: 150
tags: [enumerations]
---
-Bei einer Aufzählung (Enumeration) handelt es sich um eine spezielle Klasse, von
-der nur eine vorgegebene, endliche Anzahl an Instanzen existiert. Diese
-Instanzen werden als _Aufzählungskonstanten_ bezeichnet. Technisch gesehen
-handelt es sich bei Aufzählungskonstanten um öffentliche, statische Konstanten
-vom Typ der Aufzählung.
+Eine Aufzählung (Enumeration) ist eine spezielle Klasse, von der nur eine
+vorgegebene, endliche Anzahl an Instanzen existiert. Diese Instanzen heißen
+_Aufzählungskonstanten_ und sind technisch gesehen öffentliche, statische
+Konstanten vom Typ der Aufzählung selbst.
## Implementieren von Aufzählungen
-Die Definition einer Aufzählung erfolgt analog zur Definition von Klassen, das
-Schlüsselwort hierfür lautet `enum`.
+Eine Aufzählung wird ähnlich wie eine Klasse definiert. Das Schlüsselwort lautet
+`enum`.
```java title="WeekDay.java" showLineNumbers
public enum Weekday {
@@ -48,14 +47,12 @@ public enum Weekday {
## Verwenden von Aufzählungen
-Aufzählungen besitzen eine Reihe hilfreicher Methoden:
+Aufzählungen stellen eine Reihe hilfreicher Methoden bereit:
-- Die statische Methode `T[] values()` gibt alle Aufzählunskonstanten als Feld
- zurück
-- Die statische Methode `T valueOf(name: String)` gibt zu einer eingehenden
- Zeichenkette die dazugehörige Aufzählungskonstante zurück
-- Die Methode `int ordinal()` gibt die Ordnungszahl der Aufzählungskonstanten
- zurück
+- `T[] values()` — statisch; gibt alle Aufzählungskonstanten als Feld zurück
+- `T valueOf(name: String)` — statisch; gibt die Aufzählungskonstante zur
+ angegebenen Zeichenkette zurück
+- `int ordinal()` — gibt die nullbasierte Ordnungszahl der Konstante zurück
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/exceptions.mdx b/docs/documentation/exceptions.mdx
index 284f3c4216..8db8f535f1 100644
--- a/docs/documentation/exceptions.mdx
+++ b/docs/documentation/exceptions.mdx
@@ -9,56 +9,45 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Programmfehler (Bugs) führen dazu, dass Programme unerwartete Ergebnisse liefern
-oder abstürzen. Je komplexer das Programm, desto wichtiger wird eine durchdachte
-und konsequente Fehlerbehandlung. Man unterscheidt dabei zwischen verschiedenen
-Fehlerarten: Kompilierungsfehler, Logikfehler und Laufzeitfehler.
+oder abstürzen. Je komplexer das Programm, desto wichtiger ist eine
+strukturierte Fehlerbehandlung. Es gibt drei grundlegende Fehlerarten:
+Kompilierungsfehler, Logikfehler und Laufzeitfehler.
-Kompilierungsfehler sind Programmfehler, die verhindern, dass das Programm
-ausgeführt werden kann. Sie können relativ einfach behoben werden, da sie schon
-zur Designzeit auftreten und von den meisten Entwicklungsumgebungen direkt
-angezeigt werden.
+Kompilierungsfehler verhindern, dass das Programm übersetzt und ausgeführt
+werden kann. Da sie bereits beim Schreiben des Codes auftreten und von
+Entwicklungsumgebungen direkt angezeigt werden, lassen sie sich in der Regel
+leicht beheben.
Verhält sich das Programm nicht wie beabsichtigt, spricht man von Logikfehlern.
-Sie sind mit am schwersten zu entdecken und zu beheben. Zur Unterstüzung bei der
-Fehlersuche und -behandlung kann unter Anderem der Debugger verwendet werden.
-Der Debugger ermöglicht es, Programme zur Laufzeit zu analysieren und zu
-steuern. Durch das Setzen von Haltepunkten (Breakpoints) kann die Ausführung des
-Programms an beliebiger Stelle angehalten werden. Dadurch lassen sich z.B. die
-Inhalte von Datenobjekten überprüfen. Zudem bietet der Debugger die Möglichkeit,
-die weitere Ausführung des Programms in der gewünschten Schrittweite
-forzuführen.
+Sie sind schwer zu entdecken, da das Programm ausgeführt wird, aber falsche
+Ergebnisse liefert. Der Debugger kann dabei helfen: Er ermöglicht die
+schrittweise Ausführung und das Überprüfen von Variablenwerten zur Laufzeit.
-Laufzeitfehler treten erst beim Ausführen des Programms auf. Sie entstehen meist
-dann, wenn das Programm versucht, eine Operation auszuführen, die nicht
-ausgeführt werden kann (z.B. die Division durch Null). Diese Situationen werden
-auch als Ausnahmen (Exceptions) bezeichnet. Ausnahmen gewährleisten eine klare
-Trennung zwischen funktionalem Code und Code zur Fehlerbehandlung. Die
-Fehlerbehandlung erfolgt dabei gemäß dem Ausnahmenbehandlungsprozess: nachdem
-eine Ausnahme ausgelöst wurde, kann bzw. muss diese je nach Ausnahmenart vom
-Empfänger der Ausnahme entweder behandelt oder weitergeleitet werden
-_Catch-or-Throw-Regel_ Man unterscheidet zwischen _geprüften_ (checked) und
-_ungeprüften_ (unchecked) Ausnahmen. Geprüfte Ausnahmen müssen, ungeprüfte
-Ausnahmen können behandelt bzw. weitergeleitet werden.
+Laufzeitfehler treten erst beim Ausführen des Programms auf, wenn das Programm
+eine Operation versucht, die nicht möglich ist (z.B. Division durch null oder
+Zugriff auf ein null-Objekt). Solche Situationen werden als Ausnahmen
+(Exceptions) bezeichnet. Die Fehlerbehandlung folgt der _Catch-or-Throw-Regel_:
+Eine Ausnahme muss entweder abgefangen (catch) oder weitergeleitet (throw)
+werden. Geprüfte (checked) Ausnahmen müssen behandelt werden; ungeprüfte
+(unchecked) Ausnahmen können es.
## Die Klassenhierarchie der Laufzeitfehler
-Die Klasse `Throwable` stellt die Oberklasse aller Laufzeitfehler dar.
-Schwerwiegende Fehler (hauptsächlich Probleme in der JVM (Java Virtual Machine))
-werden durch Unterklassen der Klasse `Error` abgebildet, geprüfte Ausnahmen
-durch Unterklassen der Klasse `Exception` und ungeprüfte Ausnahmen durch
-Unterklassen der Klasse `RuntimeException`.
+`Throwable` ist die Oberklasse aller Laufzeitfehler. Schwerwiegende JVM-Fehler
+sind Unterklassen von `Error`. Geprüfte Ausnahmen sind Unterklassen von
+`Exception`, ungeprüfte Ausnahmen Unterklassen von `RuntimeException`.
```mermaid
classDiagram
@@ -72,10 +61,9 @@ classDiagram
## Definition von Ausnahmenklassen
-Eigene Ausnahmenklassen werden durch einfaches Ableiten von einer bestehenden
-Ausnahmenklasse definiert. Ausnahmenklassen sollten dabei immer von der Klasse
-`Exception` oder einer ihrer Unterklassen abgeleitet werden, nicht von der
-Klasse `Error`.
+Eigene Ausnahmenklassen werden durch Ableitung von einer bestehenden
+Ausnahmenklasse definiert. Es sollte immer von `Exception` oder einer ihrer
+Unterklassen abgeleitet werden — nicht von `Error`.
```java title="InvalidValueException.java" showLineNumbers
public class InvalidValueException extends Exception {
@@ -89,9 +77,9 @@ public class InvalidValueException extends Exception {
## Auslösen von Ausnahmen
-Mit dem Schlüsselwort `throw` kann innerhalb einer Methode eine Ausnahme
-ausgelöst werden. Die Methode, in der die Ausnahme ausgelöst wird, muss mit dem
-Schlüsselwort `throws` die Ausnahmenklasse angeben, die ausgelöst werden kann.
+Mit dem Schlüsselwort `throw` wird eine Ausnahme ausgelöst. Die auslösende
+Methode muss mit `throws` deklarieren, welche geprüften Ausnahmen sie werfen
+kann.
```java title="Computer.java (Auszug)" showLineNumbers
public abstract class Computer {
@@ -110,10 +98,9 @@ public abstract class Computer {
## Weiterleiten von Ausnahmen
-Ausnahmen können weitergeleitet werden. Hierbei wird die Fehlerbehandlung an die
-nächsthöhere Ebene weitergegeben. Um eine Ausnahme weiterzuleiten, muss in der
-weiterleitenden Methode mit `throws` die Ausnahme angegeben werden, die
-ausgelöst werden kann.
+Ausnahmen können an den Aufrufer weitergeleitet werden, anstatt sie direkt zu
+behandeln. Die weiterleitende Methode deklariert dafür ebenfalls `throws` mit
+der entsprechenden Ausnahmenklasse.
```java title="Notebook.java (Auszug)" showLineNumbers
public final class Notebook extends Computer implements Comparable {
@@ -129,11 +116,9 @@ public final class Notebook extends Computer implements Comparable {
## Abfangen von Ausnahmen
-Mit Hilfe der try-catch-Anweisung können Methoden, die eine Ausnahme auslösen
-können, überwacht werden; d.h. die Ausnahmen werden gegebenenfalls abgefangen.
-Der try-Block enthält die Anweisungen, die überwacht werden sollen, der
-catch-Block enthält die eigentliche Fehlerbehandlung. Als Parameter von `catch`
-muss angegeben werden, welche Ausnahme(n) abgefangen werden soll(en).
+Die `try-catch`-Anweisung überwacht einen Codeblock auf Ausnahmen. Der
+`try`-Block enthält den zu überwachenden Code, der `catch`-Block die
+Fehlerbehandlung für eine bestimmte Ausnahmenklasse.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/files.md b/docs/documentation/files.md
index d02c02323c..c1658ef098 100644
--- a/docs/documentation/files.md
+++ b/docs/documentation/files.md
@@ -5,18 +5,15 @@ sidebar_position: 143
tags: [java-api, files]
---
-Die Klasse `File` ermöglicht die Arbeit mit Dateien und Verzeichnissen. Mit
-Hilfe der Methode `boolean exists()` kann beispielsweise geprüft werden, ob ein
-entsprechendes Verzeichnis bzw. eine entsprechende Datei existiert oder nicht.
-Die Klasse bietet zudem M ethoden zum Erstellen und Löschen von Verzeichnissen
-bzw. Dateien. Zum Erzeugen eines File-Objekts wird entweder ein Pfad zu einem
-Verzeichnis bzw. zu einer Datei oder ein _URI_ (Unified Resource Identifier)
-benötigt.
+Die Klasse `File` ermöglicht die Arbeit mit Dateien und Verzeichnissen im
+Dateisystem. Sie bietet Methoden zum Prüfen, Erstellen und Löschen von Dateien
+und Verzeichnissen. Zum Erstellen eines `File`-Objekts wird ein Pfad oder ein
+_URI_ (Uniform Resource Identifier) angegeben.
-## Lesen von Dateien mit Hilfe der Klasse _Scanner_
+## Lesen von Dateien mit der Klasse _Scanner_
-Zum Lesen einer Datei können entweder [Datenstromklassen](io-streams) oder die
-Klasse `Scanner` verwendet werden.
+Zum zeilenweisen Lesen einer Datei kann neben den
+[Datenstromklassen](io-streams) auch die Klasse `Scanner` verwendet werden.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -45,10 +42,10 @@ Nach der letzten Verwendung sollte die Methode `void close()` der Klasse
## Absolute und relative Pfadangaben
-Beim Zugriff auf Verzeichnisse bzw. Dateien unterscheidet man zwischen absoluten
-und relativen Pfadangaben. Bei absoluten Pfadangaben wird der vollständige Pfad
-von der Wurzel des jeweiligen Verzeichnissystems bis zum Ziel angegeben, bei
-relativen der Weg von einem festgelegten Bezugspunkt bis zum Ziel.
+Bei Pfadangaben unterscheidet man zwischen absoluten und relativen Pfaden. Ein
+absoluter Pfad beschreibt den vollständigen Weg vom Wurzelverzeichnis bis zur
+Zieldatei. Ein relativer Pfad gibt den Weg ausgehend von einem festgelegten
+Bezugspunkt an.
:::info
@@ -67,8 +64,8 @@ flowchart LR
documents[documents] --> documentB[DocumentB.txt]@{ shape: doc}
```
-Die Datei `DocumentA.txt` kann entweder über den absoluten Pfad
-`C:\Temp\DocumentA.txt` oder über den relativen Pfad `documents/DocumentA.txt`
-(Bezugspunkt ist das Verzeichnis `Project`); die Datei `DocumentB.txt` über den
-absoluten Pfad `C:\workspace\Project\documents\documentB.txt` oder über den
-relativen Pfad `../../Temp/documentA.txt` angesprochen werden.
+Die Datei `DocumentA.txt` kann über den absoluten Pfad `C:\Temp\DocumentA.txt`
+oder den relativen Pfad `../../Temp/DocumentA.txt` (Bezugspunkt: `Project`)
+angesprochen werden. Die Datei `DocumentB.txt` über den absoluten Pfad
+`C:\workspace\Project\documents\DocumentB.txt` oder den relativen Pfad
+`documents/DocumentB.txt`.
diff --git a/docs/documentation/generics.md b/docs/documentation/generics.md
index ae20c7c995..5a6fbab8e4 100644
--- a/docs/documentation/generics.md
+++ b/docs/documentation/generics.md
@@ -5,20 +5,17 @@ sidebar_position: 270
tags: [generics]
---
-Quellcode sollte generell so allgemein bzw. generisch geschrieben werden, dass
-er für unterschiedliche Datenstrukturen und Datentypen verwendet werden kann.
-Das Ziel der generischen Programmierung ist die Entwicklung von
-wiederverwendbarem Code. In Java verwendet man das Konzept der generischen
-Datentypen, also Klassen, die mit verschiedene Datentypen verwendet werden
-können.
+Quellcode sollte so allgemein wie möglich geschrieben werden, damit er für
+unterschiedliche Datentypen und Datenstrukturen wiederverwendet werden kann. In
+Java wird dieses Ziel mit _generischen Datentypen_ erreicht — also Klassen, die
+mit verschiedenen Typen parametrisiert werden können.
## Generische Klassen ohne Java Generics
-Auch ohne Java Generics kann in Java mit Hilfe der Klasse `Object` generisch
-programmiert werden. Der Nachteil besteht darin, dass durch den Upcast einer
-beliebigen Klasse auf die Klasse `Object` die spezifischen Methoden der Klasse
-nicht mehr verwendet werden können und der dadurch notwendige Downcast zu
-Laufzeitfehlern führen kann.
+Auch ohne Java Generics lässt sich in Java mit der Klasse `Object` generisch
+programmieren. Der Nachteil: Durch den Upcast auf `Object` gehen die
+spezifischen Methoden der Originalklasse verloren, und der notwendige Downcast
+beim Auslesen kann zu Laufzeitfehlern führen.
Die Klasse `Box` ermöglicht das Speichern einer beliebig typisierten
Information.
@@ -49,7 +46,7 @@ public class MainClass {
public static void main(String[] args) {
Box box = new Box();
box.set(5);
- String i = (String) box.get(); // Laufzeitfehler
+ String i = (String) box.get(); // Laufzeitfehler: int ist kein String
System.out.println(i);
}
@@ -58,12 +55,11 @@ public class MainClass {
## Generische Klassen mit Java Generics
-Klassen und Methoden können in Java mit Typen parametrisiert werden. Diese
-werden durch spitze Klammern `<>` gekennzeichnet und stellen Platzhalter für
-konkrete Datentypen dar. Beim Kompilieren werden alle generischen Informationen
-vollständig entfernt und durch die konkreten Datentypen ersetzt. Durch die
-dadurch vorhandene statische Typsicherheit können Laufzeitfehler verhindert und
-Fehler bereits beim Kompilieren entdeckt werden.
+Klassen und Methoden können in Java mit Typparametern versehen werden. Diese
+werden in spitzen Klammern `<>` notiert und stellen Platzhalter für konkrete
+Datentypen dar. Beim Kompilieren ersetzt der Compiler alle generischen
+Informationen durch die konkreten Typen. Dadurch entsteht statische
+Typsicherheit, die viele Fehler bereits zur Kompilierzeit aufdeckt.
Die generische Klasse `Box` ermöglicht das Speichern einer beliebig
typisierten Information mit Hilfe des Typparameters `T`.
@@ -95,7 +91,7 @@ public class MainClass {
public static void main(String[] args) {
Box box = new Box<>();
box.set(5);
- String i = box.get(); // Kompilierungsfehler
+ String i = box.get(); // Kompilierungsfehler: Integer ist kein String
System.out.println(i);
}
@@ -146,8 +142,8 @@ public class MainClass {
## Namensrichtlinien für Typparameter
-Um den Einsatzbereich von Typparametern in generischen Klassen und Methoden
-kenntlich zu machen, sollte man festgelegte Zeichen verwenden.
+Um den Einsatzbereich von Typparametern in generischen Klassen und Methoden zu
+kennzeichnen, sollten die folgenden etablierten Kürzel verwendet werden.
| Typparameter | Einsatzbereich |
| ------------- | ----------------------------------------- |
@@ -158,10 +154,10 @@ kenntlich zu machen, sollte man festgelegte Zeichen verwenden.
## Varianz
-Bei der Deklaration einer generischen Klasse ermöglicht der Wildcard-Typ `?` die
-Angabe eines unbestimmten Typs. Dieser kann gar nicht (**Bivarianz**), nach oben
-(**Kovarianz**), nach unten (**Kontravarianz**), oder sowohl nach oben als auch
-nach unten (**Invarianz**) eingeschränkt werden.
+Mit dem Wildcard-Typ `?` kann bei der Deklaration einer generischen Klasse ein
+unbestimmter Typ angegeben werden. Dieser kann gar nicht (_Bivarianz_), nach
+oben (_Kovarianz_), nach unten (_Kontravarianz_) oder in beide Richtungen
+(_Invarianz_) eingeschränkt werden.
Die generische Klasse `Box` ermöglicht das Speichern einer beliebig
typisierten Information.
@@ -182,10 +178,9 @@ public class Box {
}
```
-In der main-methode der Startklasse werden verschiedene Boxen unterschiedlich
-deklariert und anschließend initialisiert. Dabei ist die Klasse `String` eine
-Unterklasse der Klasse `Object`, die Klasse `Integer` eine Unterklasse der
-Klasse `Number` und diese eine Unterklasse der Klasse `Object`.
+In der main-Methode der Startklasse werden verschiedene Boxen unterschiedlich
+deklariert und initialisiert. Dabei gilt: `String` und `Integer` sind
+Unterklassen von `Object`, `Integer` ist außerdem eine Unterklasse von `Number`.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/gui.md b/docs/documentation/gui.md
index 7775567fc1..27f9d0be3d 100644
--- a/docs/documentation/gui.md
+++ b/docs/documentation/gui.md
@@ -5,26 +5,22 @@ sidebar_position: 360
tags: [gui]
---
-Eine grafische Benutzeroberfläche oder auch _GUI_ (Graphical User Interface) hat
-die Aufgabe, Programme mittels grafischer Bildschirmelemente bedienbar zu
-machen. So ermöglichen _Controls_ wie Eingabefelder, Drucktasten und
-Ausgabefelder die Interaktion mit der Anwendung und _Container_ die
-strukturierte Darstellung und Verwaltung anderer Bildschirmelemente. _Dialoge_
-wie Nachrichtendialoge und Dateiauswahl-Dialoge widerum stellen vordefinierte
-Oberflächen dar, mit deren Hilfe wiederkehrende Anwendungsfälle abgedeckt werden
-können.
+Eine grafische Benutzeroberfläche (_GUI_, Graphical User Interface) macht
+Programme durch grafische Bildschirmelemente bedienbar. _Controls_ wie
+Eingabefelder, Schaltflächen und Beschriftungen ermöglichen die Interaktion.
+_Container_ ordnen und verwalten andere Bildschirmelemente. _Dialoge_ wie
+Meldungsfenster und Dateiauswahl-Dialoge decken wiederkehrende Anwendungsfälle
+ab.
## Aufbau grafischer Benutzeroberflächen
-Da es sich bei grafischen Benutzeroberflächen um komplexe Anwendungen handelt,
-werden diese in der Regel in verschiedene Bereiche wie Aufbau, Aussehen und
-Verhalten aufgeteilt (_Separation of Concerns_). Als Beispiel sei hier der
-Aufbau einer klassischen Webseite aufgeführt: HTML bestimmt den Aufbau, CSS das
-Aussehen und JavaScript das Verhalten der Webseite.
+Da grafische Benutzeroberflächen komplex sind, werden sie nach dem Prinzip der
+_Separation of Concerns_ in Bereiche wie Aufbau, Aussehen und Verhalten
+aufgeteilt. Ein bekanntes Beispiel ist eine klassische Webseite: HTML definiert
+den Aufbau, CSS das Aussehen und JavaScript das Verhalten.
-Das Entwurfmuster MVC (_Model-View-Controller_) stellt einen gängigen Ansatz zur
-Entwicklung von grafischen Benutzeroberflächen dar, bei dem die grafische
-Benutzeroberfläche in drei Bereiche unterteilt wird:
+Das Entwurfsmuster MVC (_Model-View-Controller_) ist ein gängiger Ansatz für
+GUI-Entwicklung und teilt die Oberfläche in drei Bereiche auf:
- Das _Model_ ist für die Datenhaltung und -verwaltung zuständig
- Die _View_ ist für die Darstellung der Oberfläche zuständig, welche wiederum
@@ -49,13 +45,10 @@ MVP (_Model-View-Presenter_) oder MVVM (_Model-View-ViewModel_) verwendet.
## Ereignisse (Events)
-Ereignisse (Events) sind Nachrichten, die über das System weitergeleitet werden.
-Auf grafischen Benutzeroberflächen werden Ereignisse z.B. durch das Betätigen
-einer Drucktaste ausgelöst. Weitere typische Ergeignisse sind das Betätigen
-einer Maustaste, Tastatureingaben oder das Vergrößern bzw. Verkleinern eines
-Fensters.
-
-Die Behandlung dieser Ereignisse wird durch das Delegationsmodell festgelegt:
+Ereignisse (Events) sind Nachrichten, die durch Benutzerinteraktionen ausgelöst
+werden — z.B. durch das Klicken einer Schaltfläche, eine Tastatureingabe oder
+das Vergrößern eines Fensters. Das Delegationsmodell legt fest, wie Ereignisse
+behandelt werden:
1. Empfänger können sich beim Sender für ein Ereignis registrieren
2. Der Sender löst das Ereignis aus und übergibt das erzeugte Ereignis-Objekt an
diff --git a/docs/documentation/hashing.mdx b/docs/documentation/hashing.mdx
index 9c654af540..37fa66276b 100644
--- a/docs/documentation/hashing.mdx
+++ b/docs/documentation/hashing.mdx
@@ -8,11 +8,9 @@ tags: [hashing]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Unter Schlüsseltransformationen (Hashing) versteht man die Transformation einer
-großen Datenmenge in eine kleinere. Die größere Datenmenge wird dabei als
-Schlüssel, die kleinere als Hashcode bezeichnet. Die Transformation erfolgt über
-eine sogenannte Hashfunktion (auch Streuwertfunktion). Wichtig dabei ist, dass
-der Hashcode nur vom Zustand des Schlüssels abhängen darf.
+Schlüsseltransformation (Hashing) bezeichnet die Abbildung einer großen
+Datenmenge (Schlüssel) auf eine kleinere Datenmenge (Hashcode) mittels einer
+Hashfunktion. Der Hashcode darf dabei nur vom Zustand des Schlüssels abhängen.
```mermaid
flowchart
@@ -24,11 +22,10 @@ flowchart
## Hashtabellen
-Hashtabellen sind spezielle Datenstrukturen, die für den schnellen Zugriff
-konzipiert wurden. Mit Hilfe einer Hashfunktion wird der Index berechnet, an der
-ein Schlüssel gespeichert wird. Bei Hashtabellen soll durch das Hashing eine
-gleichmäßige Streuung der Einträge in der Tabelle erreicht werden. Aus diesem
-Grund werden Hashtabellen auch als Streuwerttabellen bezeichnet.
+Hashtabellen sind Datenstrukturen für schnellen Zugriff. Der Index eines
+Eintrags wird über eine Hashfunktion berechnet, sodass Einträge gleichmäßig in
+der Tabelle gestreut sind. Daher werden Hashtabellen auch Streuwerttabellen
+genannt.
| Index | Schlüssel | Hashcode |
| ----- | --------- | -------- |
@@ -40,11 +37,15 @@ Grund werden Hashtabellen auch als Streuwerttabellen bezeichnet.
## Hashfunktionen
+Eine Hashfunktion berechnet aus einem Schlüssel (Hashcode) einen Tabellenindex.
+Die beiden gebräuchlichsten Verfahren sind die Divisionsrestmethode und die
+multiplikative Methode.
+
-Die Divisionsrest-Methode stellt eine einfache und schnelle Hashfunktion dar.
-Die Berechnung des Index erfolgt dabei gemäß der Formel `ℎ(𝑘) = 𝑘 𝑚𝑜𝑑 𝑚`.
+Die Divisionsrestmethode ist eine einfache und schnelle Hashfunktion. Der Index
+wird nach der Formel `ℎ(𝑘) = 𝑘 𝑚𝑜𝑑 𝑚` berechnet.
| Schlüssel | Hashcode | Index |
| --------- | -------- | ------------- |
@@ -62,9 +63,8 @@ Die Berechnung des Index erfolgt dabei gemäß der Formel `ℎ(𝑘) = 𝑘 𝑚
-Die Multiplikative Methode stellt eine Hashfunktion dar, die man als
-Verallgemeinerung der Divisionsrest-Methode sehen kann. Die Berechnung des Index
-erfolgt dabei gemäß der Formel `ℎ(𝑘) = ⌊𝑚 ∗ (𝑘 ∗ 𝐴 𝑚𝑜𝑑 1)⌋`.
+Die multiplikative Methode ist eine Verallgemeinerung der Divisionsrestmethode.
+Der Index wird nach der Formel `ℎ(𝑘) = ⌊𝑚 ∗ (𝑘 ∗ 𝐴 𝑚𝑜𝑑 1)⌋` berechnet.
| Schlüssel | Hashcode | Index |
| --------- | -------- | ---------------------------- |
@@ -91,20 +91,19 @@ Als Wert für die Konstante 𝐴 wird gerne der Goldene Schnitt (~0,62) verwende
## Kollisionen
-Werden zu unterschiedlichen Schlüsseln dieselben Indizes ermittelt, entstehen
-dadurch sogenannte Kollisionen. Um Kollisionen bestmöglichen zu vermeiden, muss
-eine geeignete Tabellengröße sowie eine geeignete Hashfunktion gewählt werden.
-Zur Auflösung von Kollisionen gibt es verschiedene Möglichkeiten.
+Ergibt die Hashfunktion für zwei unterschiedliche Schlüssel denselben Index,
+spricht man von einer Kollision. Um Kollisionen zu minimieren, müssen
+Tabellengröße und Hashfunktion sorgfältig gewählt werden. Für unvermeidliche
+Kollisionen gibt es zwei grundlegende Auflösungsstrategien.
-Beim geschlossenen Hashing mit offener Adressierung wird bei einer Kollision
-über unterschiedliche Verfahren eine freie Stelle in der Hashtabelle gesucht:
-Beim linearen Sondieren wird mit festen Intervallschritten nach einer freien
-Stelle gesucht, beim quadratischen Sondieren wird der Intervallschritt nach
-jedem erfolglosen Versuch quadriert und beim doppelten Hashing wird der
-Intervallschritt mit Hilfe einer zusätzlichen Hashfunktion berechnet.
+Beim geschlossenen Hashing wird bei einer Kollision eine freie Stelle in der
+Hashtabelle gesucht. Beim linearen Sondieren geschieht dies mit festen
+Intervallschritten, beim quadratischen Sondieren wächst der Schritt quadratisch,
+und beim doppelten Hashing wird der Schritt über eine zweite Hashfunktion
+berechnet.
| Index | Schlüssel |
| ----- | --------- |
@@ -117,11 +116,9 @@ Intervallschritt mit Hilfe einer zusätzlichen Hashfunktion berechnet.
-Beim offenen Hashing mit geschlossener Adressierung werden alle Schlüssel mit
-demselben Index in einem Behälter (Bucket) gespeichert. Diese Behälter werden
-oft mit Hilfe linearer Listen realisiert. Bei der Suche nach einem Schlüssel
-muss also zunächst der richtige Behälter ermittelt und anschließend der Behälter
-durchsucht werden.
+Beim offenen Hashing werden alle Schlüssel mit demselben Index in einem Behälter
+(Bucket) gespeichert, der in der Regel als verkettete Liste realisiert wird. Bei
+einer Suche wird zuerst der Bucket bestimmt, dann der Bucket durchsucht.
| Index | Schlüssel |
| ----- | ------------- |
diff --git a/docs/documentation/inheritance.mdx b/docs/documentation/inheritance.mdx
index 0cb622f3d9..9d0859d184 100644
--- a/docs/documentation/inheritance.mdx
+++ b/docs/documentation/inheritance.mdx
@@ -9,22 +9,19 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Bei der Modellierung von Klassen stellt man häufig fest, dass sich einige
-Klassen der Struktur und dem Verhalten nach ähneln. In solchen Fällen hat man
-die Möglichkeit, die gemeinsamen Strukturen und Verhaltensweisen aus den
-speziellen Klassen zu extrahieren und in einer allgemeineren Klasse
-unterzubringen. Dies wird als _Generalisierung_ bezeichnet. Umgekehrt gibt es
-oftmals auch Bedarf, eine bestehende Klasse um zusätzliche Attribute und/oder
-Methoden zu erweitern. Dies bezeichnet man als _Spezialisierung_ Die Beziehung
-zwischen einer speziellen Klasse und einer allgemeinen Klasse wird _Vererbung_
-bezeichnet. Die speziellen Klasse einer Vererbung werden als _Unterklassen_ (Sub
-Classes), die allgemeinen Klassen als _Oberklassen_ (Super Classes) bezeichnet.
+Klassen in Struktur und Verhalten ähneln. In solchen Fällen können die
+gemeinsamen Teile in einer allgemeineren Klasse zusammengefasst werden
+(_Generalisierung_). Umgekehrt lässt sich eine bestehende Klasse um zusätzliche
+Attribute und Methoden erweitern (_Spezialisierung_). Die Beziehung zwischen
+einer speziellen und einer allgemeinen Klasse nennt man _Vererbung_. Die
+spezielle Klasse heißt _Unterklasse_ (Sub Class), die allgemeine _Oberklasse_
+(Super Class).
## Implementieren von Vererbung
-Die Vererbung wird mit dem Schlüsselwort `extends` realisiert. In der Oberklasse
-können Attribute und Methoden mit dem Schlüsselwort `protected` als geschützt
-festlegt werden. Unterklassen können auf alle öffentlichen und geschützten
-Attribute und Methoden der Oberklasse zugreifen.
+Vererbung wird mit dem Schlüsselwort `extends` realisiert. Attribute und
+Methoden der Oberklasse können mit `protected` als geschützt markiert werden,
+sodass Unterklassen darauf zugreifen können.
@@ -69,18 +66,17 @@ public class Notebook extends Computer {
:::info
-In den Konstruktoren der Unterklasse muss ein Konstruktor der Oberklasse mit
-Hilfe von `super` aufgerufen werden.
+Im Konstruktor einer Unterklasse muss mit `super(...)` ein Konstruktor der
+Oberklasse aufgerufen werden.
:::
## Überschreiben von Methoden
-Wird in einer Unterklasse eine Methode definiert, die der Signatur einer Methode
-der Oberklasse entspricht, wird die Methode der Oberklasse _überschrieben_, d.h.
-von der Unterklasse neu implementiert. Bei Bedarf kann die ursprüngliche
-Methodenimplementierung der Oberklasse mit Hilfe der Objektreferenz `super`
-aufgerufen werden.
+Definiert eine Unterklasse eine Methode mit derselben Signatur wie die
+Oberklasse, _überschreibt_ sie diese Methode und ersetzt damit ihre
+Implementierung. Die ursprüngliche Implementierung der Oberklasse kann bei
+Bedarf über `super` aufgerufen werden.
diff --git a/docs/documentation/inner-classes.mdx b/docs/documentation/inner-classes.mdx
index 1b6200994c..ab728adc7d 100644
--- a/docs/documentation/inner-classes.mdx
+++ b/docs/documentation/inner-classes.mdx
@@ -8,19 +8,18 @@ tags: [inner-classes]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Java bietet die Möglichkeit, Klassen und Schnittstellen zu verschachteln. Das
-Ziel von inneren Klassen ist eine Definition von Hilfsklassen möglichst nahe an
-der Stelle, wo sie gebraucht werden. Beispiele für Hilfsklassen sind
-Ausnahmeklassen, Komparatoren und Ereignisbehandler. Alle bisherigen Klassen
-werden auch als _äußerer Klassen_ bzw. _Top-Level-Klassen_ bezeichnet.
+Java erlaubt es, Klassen und Schnittstellen zu verschachteln. Ziel innerer
+Klassen ist es, Hilfsklassen möglichst nah an der Stelle zu definieren, wo sie
+benötigt werden — z.B. Ausnahmeklassen, Komparatoren oder Ereignisbehandler.
+Alle bisher bekannten Klassen, die auf der obersten Ebene definiert sind, nennt
+man auch _äußere Klassen_ oder _Top-Level-Klassen_.
## Geschachtelte Klassen (Nested Classes)
-Geschachtelte Klassen sind Top-Level-Klassen, die zur Strukturierung des
-Namensraumes in anderen Top-Level-Klassen definiert sind. Ein Namensraum ist die
-vollständige Pfadangabe zur Klasse (z.B. `java.lang`). Geschachtelte Klassen
-müssen statisch definiert werden und sind daher im eigentlichen Sinne keine
-richtigen inneren Klassen.
+Geschachtelte Klassen sind statische Top-Level-Klassen, die innerhalb einer
+anderen Top-Level-Klasse zur Strukturierung des Namensraums definiert werden. Da
+sie statisch sein müssen, sind sie im eigentlichen Sinne keine echten inneren
+Klassen.
@@ -54,11 +53,11 @@ public class MainClass {
## Elementklassen (Member Classes)
-Objekte von Elementklassen sind immer mit einem Objekt der umgebenden Klasse
-verbunden. Dies ermöglicht die Umsetzung von Kompositionen (siehe
+Objekte von Elementklassen sind immer an ein Objekt der umgebenden Klasse
+gebunden. Das ermöglicht die Umsetzung von Kompositionen (siehe
[Darstellung von Assoziationen](class-diagrams#darstellung-von-assoziationen)).
-Sie haben Zugriff auf alle Variablen und Methoden der sie umgebenden Klasse und
-dürfen keine statischen Elemente enthalten.
+Elementklassen haben Zugriff auf alle Variablen und Methoden der umgebenden
+Klasse, dürfen aber keine statischen Elemente enthalten.
@@ -79,8 +78,8 @@ public class MainClass {
public static void main(String[] args) {
List list = new List();
- List.Item item = new List.Item(); // Kompilierungsfehler
- List.Item item = list.new Item();
+ List.Item item = new List.Item(); // Kompilierungsfehler: Elementklasse benötigt umgebendes Objekt
+ List.Item item = list.new Item(); // korrekt
}
}
@@ -91,11 +90,10 @@ public class MainClass {
## Lokale Klassen
-Lokale Klassen werden innerhalb einer Methode definiert und können auch nur dort
-verwendet werden. Sie dürfen nicht als `public`, `protected`, `private` oder
-`static` definiert werden, dürfen keine statischen Elemente enthalten und können
-nur die mit `final` markierten Variablen und Parameter der umgebenden Methode
-verwenden.
+Lokale Klassen werden innerhalb einer Methode definiert und sind auch nur dort
+verwendbar. Sie dürfen nicht als `public`, `protected`, `private` oder `static`
+deklariert werden, dürfen keine statischen Elemente enthalten und können nur auf
+`final`-markierte Variablen und Parameter der umgebenden Methode zugreifen.
@@ -151,12 +149,11 @@ public class MainClass {
## Anonyme Klassen
-Anonyme Klassen besitzen im Gegensatz zu lokalen Klassen keinen Namen und werden
-innerhalb eines Ausdrucks definiert und instanziiert; Klassendeklaration und
-Objekterzeugung sind also in einem Sprachkonstrukt vereint. Wird als Datentyp
-eine Schnittstelle benötigt, implementiert die anonyme Klasse diese
-Schnittstelle, wird als Datentyp eine Klasse benötigt, so wird die anonyme
-Klasse daraus abgeleitet.
+Anonyme Klassen haben im Gegensatz zu lokalen Klassen keinen Namen. Sie werden
+direkt innerhalb eines Ausdrucks definiert und instanziiert — Klassendeklaration
+und Objekterzeugung sind also in einem Konstrukt vereint. Ist der erwartete
+Datentyp eine Schnittstelle, implementiert die anonyme Klasse diese; ist es eine
+Klasse, wird daraus abgeleitet.
diff --git a/docs/documentation/interfaces.mdx b/docs/documentation/interfaces.mdx
index 03db25a094..d6950b328f 100644
--- a/docs/documentation/interfaces.mdx
+++ b/docs/documentation/interfaces.mdx
@@ -8,14 +8,13 @@ tags: [interfaces]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Wird eine Klasse von mehreren Klassen abgeleitet, spricht man von
-Mehrfachvererbung. Das Prinzip der Mehrfachvererbung wird von vielen
-Programmiersprachen allerdings nicht (direkt) unterstützt. Der Hauptgrund hier
-sind mögliche Mehrdeutigkeiten. Erbt eine Klasse über mehrere mögliche Pfade von
-einer Basisklasse und werden dabei möglicherweise Methoden der Basisklasse
-unterschiedlich überschrieben, entstehen dadurch nicht eindeutige Varianten.
-Aufgrund der Rautenform des Klassendiagramms wird dieses Szenario also
-_Diamantenproblem_ bezeichnet.
+Erbt eine Klasse von mehreren Klassen gleichzeitig, spricht man von
+_Mehrfachvererbung_. Dieses Konzept wird von vielen Programmiersprachen nicht
+direkt unterstützt, da es zu Mehrdeutigkeiten führen kann: Erbt eine Klasse über
+mehrere Pfade von derselben Basisklasse und wurde dabei eine Methode
+unterschiedlich überschrieben, entsteht Unklarheit, welche Implementierung
+verwendet werden soll. Aufgrund der Rautenform im Klassendiagramm bezeichnet man
+dieses Problem als _Diamantenproblem_.
```mermaid
classDiagram
@@ -36,17 +35,17 @@ classDiagram
}
```
-Zur Lösung des Diamantenproblems werden Schnittstellen (Interfaces) verwendet.
-Schnittstellen sind im Prinzip abstrakte Klassen, die ausschließlich abstrakte
-Methoden besitzen. Durch Schnittstellen wird sichergestellt, dass Klassen
-bestimmte Methoden bereitstellen und dass verschiedene Klassen miteinander
-kommunizieren können.
+Zur Lösung des Diamantenproblems werden Schnittstellen (Interfaces) eingesetzt.
+Schnittstellen sind im Wesentlichen abstrakte Klassen, die ausschließlich
+abstrakte Methoden enthalten. Sie stellen sicher, dass implementierende Klassen
+bestimmte Methoden bereitstellen, ohne eine konkrete Vererbungshierarchie
+vorzuschreiben.
## Definition von Schnittstellen
-Die Definition einer Schnittstelle erfolgt analog zur Definition von Klassen.
-Das Schlüsselwort für Schnittstellen lautet `interface`. Eine Schnittstelle kann
-nur öffentliche, abstrakte und öffentliche, statische Methoden beinhalten.
+Eine Schnittstelle wird ähnlich wie eine Klasse definiert, verwendet aber das
+Schlüsselwort `interface`. Sie kann nur öffentliche abstrakte sowie öffentliche
+statische Methoden enthalten.
```java title="MobileDevice.java" showLineNumbers
public interface MobileDevice {
@@ -64,9 +63,9 @@ Die Angabe von `abstract` und `public` bei Methoden ist nicht erforderlich.
## Implementieren von Schnittstellen
-Schnittstellen werden mit Hilfe des Schlüsselworts `implements` von einer Klasse
-implementiert. Durch die Implementierung der Schnittstelle verpflichtet sich die
-Klasse, alle Methoden der Schnittstelle zu implementieren.
+Eine Schnittstelle wird mit dem Schlüsselwort `implements` von einer Klasse
+implementiert. Damit verpflichtet sich die Klasse, alle Methoden der
+Schnittstelle zu implementieren.
@@ -98,9 +97,9 @@ public class Notebook extends Computer implements MobileDevice {
## Verwenden von Schnittstellen
-Schnittstellen können ebenso wie Klassen als Datentypen verwendet werden. Die
+Schnittstellen können wie Klassen als Datentypen verwendet werden. Die
Typumwandlung von der implementierenden Klasse zur Schnittstelle bezeichnet man
-als _Upcast_ die Rückumwandlung als _Downcast_
+als _Upcast_, die Rückumwandlung als _Downcast_.
diff --git a/docs/documentation/introduction.mdx b/docs/documentation/introduction.mdx
index 870bc61162..1e307f40bd 100644
--- a/docs/documentation/introduction.mdx
+++ b/docs/documentation/introduction.mdx
@@ -10,24 +10,23 @@ import Contributor from '@site/src/components/Contributor';
# Einführung
-1995 veröffentliche die Firma Sun Microsystems die Programmiersprache Java.
-Diese hat sich im Laufe der Zeit als universelle, für vielfältige Zwecke
-einsetzbare Lösung und als Quasi-Standard für die plattformunabhängige
-Entwicklung etabliert. Zudem war Java einer der maßgeblichen Wegbereiter für die
-Verbreitung des objektorientierten Programmierparadigmas, welches gemeinhin in
-vielen Bereichen als State-of-the-Art gilt.
+1995 veröffentlichte die Firma Sun Microsystems die Programmiersprache Java. Sie
+hat sich seitdem als universelle, vielseitig einsetzbare Lösung und als
+Quasi-Standard für die plattformunabhängige Softwareentwicklung etabliert. Zudem
+war Java einer der wichtigsten Wegbereiter für die Verbreitung des
+objektorientierten Programmierparadigmas, das heute in vielen Bereichen als
+Stand der Technik gilt.
-Diese Webseite sowie die dazugehörigen Vorlesungen sollen eine systematische
-Einführung in das Programmieren mit Java ermöglichen. Hierzu werden wichtige,
-praxisrelevante Konzepte und Methoden der Programmierung vorgestellt, wobei die
-objektorientierte Programmierung einen großen Raum einnimmt.
+Diese Webseite und die dazugehörigen Vorlesungen bieten eine systematische
+Einführung in das Programmieren mit Java. Es werden wichtige, praxisrelevante
+Konzepte und Methoden der Programmierung vorgestellt, wobei die
+objektorientierte Programmierung einen großen Schwerpunkt bildet.
-Wir stellen grundsätzliche alle Inhalte der Vorlesung (Dokumentation,
-Abbildungen, Quellcode) in Textform bereit (_Everything as Code_). Da
-professionelle Softwareentwicklung immer auch Zusammenarbeit bedeutet, möchten
-wir zudem auf moderne Art und Weise (z.B. per Issues, Pull Requests oder
-Discussions) die Studierenden zu eben dieser Zusammenarbeit animieren
-(_Community by Design_).
+Alle Inhalte der Vorlesung (Dokumentation, Abbildungen, Quellcode) werden in
+Textform bereitgestellt (_Everything as Code_). Da professionelle
+Softwareentwicklung immer auch Zusammenarbeit bedeutet, werden Studierende
+eingeladen, auf moderne Art und Weise — z.B. per Issues, Pull Requests oder
+Discussions — aktiv mitzuwirken (_Community by Design_).
## Contributors
diff --git a/docs/documentation/io-streams.md b/docs/documentation/io-streams.md
index b777a56fa0..60f12197d9 100644
--- a/docs/documentation/io-streams.md
+++ b/docs/documentation/io-streams.md
@@ -5,17 +5,13 @@ sidebar_position: 340
tags: [io-streams]
---
-Datenströme (IO-Streams) sind unidirektionale Pipelines, die Schnittstellen
-eines Java-Programms nach außen darstellen. Daten können unabhängig von der Art
-der Quelle bzw. des Ziels vorne in einen Datenstrom geschrieben und hinten
-wieder ausgelesen werden. Ein Datenstrom kann dabei immer nur in eine Richtung
-verwendet werden (also entweder zur Ein- oder Ausgabe). Neben den
-Standard-Datenströmen zur Ein- und Ausgabe existieren verschiedene Klassen zum
-Schreiben und Lesen zeichenorientierter Daten, zum Schreiben und Lesen
-byteorientierter Daten und zum Schreiben und Lesen serialisierter Objekte. Das
-Arbeiten mit Datenstrom-Klassen kann dabei aufwändig über "normale"
-try-catch-Anweisungen oder mit Hilfe von try-with-resources-Anweisungen
-realisiert werden.
+Datenströme (IO-Streams) sind unidirektionale Pipelines zwischen einem
+Java-Programm und einer Datenquelle oder einem Datenziel. Daten werden vorne in
+den Strom geschrieben und hinten wieder ausgelesen. Ein Datenstrom kann dabei
+immer nur in eine Richtung verwendet werden — entweder zur Eingabe oder zur
+Ausgabe. Java bietet Klassen für zeichenorientierte Daten (z.B. Textdateien),
+byteorientierte Daten (z.B. Bilddateien) und serialisierte Objekte. Für das
+korrekte Schließen der Ströme empfiehlt sich die `try-with-resources`-Anweisung.
```mermaid
flowchart LR
@@ -29,8 +25,9 @@ flowchart LR
## Standard-Datenströme zur Ein- und Ausgabe
-Java stellt Standard-Datenströme für die Eingabe (`System.in`), die Ausgabe
-(`System.out`), sowie die Fehlerausgabe (`System.err`) zur Verfügung.
+Java stellt drei Standard-Datenströme bereit: `System.in` für die
+Standardeingabe (Tastatur), `System.out` für die Standardausgabe (Konsole) und
+`System.err` für die Fehlerausgabe.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -64,9 +61,8 @@ ermöglicht eine einfache Möglichkeit der Eingabe.
## Schreiben und Lesen byteorientierter Daten
-Für die Verarbeitung von byteorientierten Daten (z.B. Bild- und Video-Dateien)
-stehen die abstrakten Basisklassen `InputStream` und `OutputStream` zur
-Verfügung.
+Für die Verarbeitung byteorientierter Daten wie Bild- oder Videodateien stehen
+die abstrakten Basisklassen `InputStream` und `OutputStream` zur Verfügung.
| Datenstromklasse | Ein- und Ausgabe in... |
| ------------------------------------------------ | ---------------------- |
@@ -125,8 +121,8 @@ public class MainClass {
## Schreiben und Lesen zeichenorientierter Daten
-Für die Verarbeitung von zeichenorientierten Daten (z.B. Textdokumente) stehen
-die abstrakten Basisklassen `Reader` und `Writer` zur Verfügung.
+Für die Verarbeitung zeichenorientierter Daten wie Textdateien stehen die
+abstrakten Basisklassen `Reader` und `Writer` zur Verfügung.
| Datenstromklasse | Ein- und Ausgabe in... |
| ------------------------------------- | ---------------------- |
@@ -187,18 +183,15 @@ public class MainClass {
## Schreiben und Lesen serialisierter Objekte
-Um ein Objekt persistent zu machen (also zu sichern) und um ein Objekt durch das
-Netzwerk zu schicken (also für entfernte Methodenaufrufe) ist es notwendig, das
-Objekt in einen Byte-Strom umzuwandeln. Die Umwandlung eines Objektes in einen
-Byte-Strom bezeichnet man als _Serialisierung_ die Rückumwandlung als
-_Deserialisierung_ Die Serialisierung erfolgt über die writeObject-Methode der
-Klasse `ObjectOutputStream`, die Deserialisierung über die readObject-Methode
-der Klasse `ObjectInputStream`.
+Serialisierung bezeichnet die Umwandlung eines Objekts in einen Byte-Strom, z.B.
+zum Speichern in einer Datei oder zum Versenden über ein Netzwerk. Der
+umgekehrte Vorgang wird als _Deserialisierung_ bezeichnet. Die Serialisierung
+erfolgt mit der Methode `writeObject()` der Klasse `ObjectOutputStream`, die
+Deserialisierung mit `readObject()` der Klasse `ObjectInputStream`.
-Damit Objekte einer Klasse serialisiert werden können, muss die entsprechende
-Klasse die Schnittstelle `Serializable` implementieren. Die Schnittstelle
-`Serializable` ist eine sogenannte Marker-Schnittstelle, d.h. sie besitzt keine
-zu implementierenden Methoden.
+Damit Objekte einer Klasse serialisiert werden können, muss die Klasse die
+Schnittstelle `Serializable` implementieren. Diese sogenannte
+Marker-Schnittstelle besitzt keine zu implementierenden Methoden.
```java title="Foo.java" showLineNumbers
public record Stark(String name) implements Serializable {}
@@ -248,31 +241,31 @@ public class MainClass {
```java title="MainClass.java" showLineNumbers
public class MainClass {
- public static void main(String[] args) {
- File file = new File("starks.bin");
+ public static void main(String[] args) {
+ File file = new File("starks.bin");
- try (FileInputStream fis = new FileInputStream(file);
- ObjectInputStream ois = new ObjectInputStream(fis)) {
- while (true) {
- Stark stark = (Stark) ois.readObject();
- System.out.println(stark);
+ try (FileInputStream fis = new FileInputStream(file);
+ ObjectInputStream ois = new ObjectInputStream(fis)) {
+ while (true) {
+ Stark stark = (Stark) ois.readObject();
+ System.out.println(stark);
+ }
+ } catch (EOFException e) {
+ // Dateiende erreicht
+ } catch (IOException | ClassNotFoundException e) {
+ e.printStackTrace();
}
- } catch (EOFException e) {
- /* End of File */
- } catch (IOException | ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
+ }
}
```
### Versionierung bei der Serialisierung
-Die Konstante `serialVersionUID` vom Datentyp `long` dient zur eindeutigen
-Identifikation der Version einer serialisierbaren Klasse. Durch die Konstante
-kann sichergestellt werden, dass Empfänger von serialisierten Objekten
-typkompatibel zum Sender sind, d.h. eine passende Klassenstruktur aufweisen.
+Die Konstante `serialVersionUID` vom Typ `long` identifiziert eindeutig die
+Version einer serialisierbaren Klasse. Sie stellt sicher, dass eine
+deserialisierte Klasse dieselbe Struktur besitzt wie die ursprünglich
+serialisierte Klasse.
```java title="Foo.java" showLineNumbers
public record Stark(String name) implements Serializable {
@@ -291,8 +284,8 @@ Zuweisung dringend empfohlen.
## Die try-with-resources-Anweisung
-Bei einer "normalen" try-catch-Anweisung müssen die Datenstrom-Klassen manuell
-geschlossen werden, was sich als sehr aufwändig darstellt.
+Bei einer gewöhnlichen `try-catch`-Anweisung müssen Datenstrom-Objekte manuell
+im `finally`-Block geschlossen werden, was schnell unübersichtlich wird.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -328,8 +321,8 @@ Der finally-Block einer try-Anweisung wird in jedem Fall durchlaufen.
:::
-Die try-with-resources-Anweisung ermöglicht die Deklaration von Ressourcen, die
-am Ende des try-Blockes automatisch geschlossen werden.
+Die `try-with-resources`-Anweisung deklariert Ressourcen direkt im `try`-Kopf
+und schließt sie automatisch am Ende des Blocks.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -350,7 +343,7 @@ public class MainClass {
:::info
-Voraussetzung für den Einsatz der try-with-resources-Anweisung ist, dass die
-Ressourcen-Klassen die Schnittstelle `AutoCloseable` implementiert haben.
+Voraussetzung für den Einsatz der `try-with-resources`-Anweisung ist, dass die
+verwendeten Klassen die Schnittstelle `AutoCloseable` implementieren.
:::
diff --git a/docs/documentation/java-api.md b/docs/documentation/java-api.md
index 239c25350c..3bba992e69 100644
--- a/docs/documentation/java-api.md
+++ b/docs/documentation/java-api.md
@@ -5,11 +5,12 @@ sidebar_position: 140
tags: [java-api]
---
-Die _Java API_ (Java Application Programming Interface) stellt eine umfangreiche
-Bibliothek wichtiger Java-Klassen dar. Neben dem eigentlichen Quellcode stellt
-die Java API auch detaillierte Informationen zu den Klassen (Paketzugehörigkeit,
-Attribute, Methoden,…) als Javadoc bereit. Entwicklungsumgebungen wie Eclipse
-bieten meist eine vollständige Integration der Java API an.
+Die _Java API_ (Application Programming Interface) ist eine umfangreiche
+Standardbibliothek, die fertige Klassen und Schnittstellen für häufige
+Programmieraufgaben bereitstellt. Zusätzlich zum Quellcode enthält die Java API
+eine Javadoc-Dokumentation mit Informationen zu Paketen, Klassen, Attributen und
+Methoden. Entwicklungsumgebungen wie Eclipse oder IntelliJ IDEA integrieren die
+Java API direkt in die Code-Vervollständigung.
## Wichtige Klassen und Schnittstellen der Java API
@@ -36,14 +37,13 @@ bieten meist eine vollständige Integration der Java API an.
## Die Javadoc
-Die Javadoc ist ein Werkzeug zur Software-Dokumentation und erstellt aus den
+Die Javadoc ist ein Werkzeug zur Software-Dokumentation. Es erstellt aus den
öffentlichen Deklarationen von Klassen, Schnittstellen, Attributen und Methoden
-sowie eventuell vorhandenen
+sowie optionalen
[Dokumentationskommentaren](class-structure#kommentare-und-dokumentation)
-HTML-Seiten. Um die Navigation innerhalb der Dokumentationsdateien zu
-erleichtern, werden zusätzlich verschiedene Index- und Hilfsdateien generiert.
-HTML-Tags in den Dokumentationskommentaren ermöglichen die Formatierung der
-Dokumentation.
+HTML-Seiten. Zur einfacheren Navigation werden zusätzlich Index- und
+Hilfsdateien generiert. HTML-Tags in den Kommentaren ermöglichen die
+Formatierung der Dokumentation.
```java title="Computer.java (Auszug)" showLineNumbers
/**
diff --git a/docs/documentation/java-collections-framework.mdx b/docs/documentation/java-collections-framework.mdx
index ba26a00a9e..0fcfac0849 100644
--- a/docs/documentation/java-collections-framework.mdx
+++ b/docs/documentation/java-collections-framework.mdx
@@ -8,20 +8,17 @@ tags: [collections, lists, sets, queues]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Collections sind Behälter, die beliebig viele Objekte aufnehmen können. Der
-Behälter übernimmt dabei die Verantwortung für die Elemente. Collections werden
-auch als (Daten-)Sammlungen bezeichnet. Alle Collections-Schnittstellen und
-Klassen befinden sich im Paket `java.util`. Die Grundformen der Datensammlungen
-sind die Schnittstellen `List`, `Set` und `Queue`. Zu allen
-Schnittstellen existieren konkrete Implementierungen sowie abstrakte Klassen,
-die zum Erstellen eigener Collections-Klassen verwendet werden können.
+Das Java Collections Framework stellt Schnittstellen und Klassen für
+Datensammlungen bereit. Alle Collections-Typen befinden sich im Paket
+`java.util`. Die drei Grundformen sind `List`, `Set` und `Queue`, zu
+denen jeweils konkrete Implementierungen existieren.
-Unter einer Liste (List) versteht man eine geordnete Folge von Objekten. Listen
-können doppelte Elemente enthalten. Der Zugriff auf die Elemente erfolgt über
-den Index oder sequentiell.
+Eine Liste ist eine geordnete Folge von Objekten, die doppelte Elemente
+enthalten darf. Der Zugriff auf die Elemente erfolgt über den Index oder
+sequentiell.
```mermaid
flowchart
@@ -40,9 +37,9 @@ Konkrete Implementierungen der Schnittstelle `List` stellen die Klassen
-Unter einer Menge (Set) versteht man eine Ansammlung von Elementen. Mengen
-können keine doppelten Elemente beinhalten. Der Zugriff erfolgt über typische
-Mengenoperationen.
+Eine Menge ist eine Ansammlung von Objekten, die keine doppelten Elemente
+enthalten darf. Der Zugriff erfolgt über typische Mengenoperationen wie
+Vereinigung, Schnittmenge und Differenz.
```mermaid
flowchart LR
@@ -61,11 +58,10 @@ Binärbaumes.
-Unter einer Warteschlange (Queue) versteht man eine Folge von Objekten, bei der
-das Anfügen und Löschen von Objekten nach dem FIFO-Prinzip (First In First Out)
-funktioniert. Bei einer Warteschlange kann ein neues Objekt immer nur am Ende
-angefügt werden und nur das Objekt, das am Anfang der Warteschlange steht,
-gelöscht werden. Warteschlangen können doppelte Elemente enthalten.
+Eine Warteschlange ist eine Folge von Objekten, bei der Elemente nach dem
+FIFO-Prinzip (First In, First Out) verwaltet werden: Neue Elemente werden am
+Ende eingefügt, entnommen wird immer das vorderste Element. Doppelte Elemente
+sind erlaubt.
```mermaid
flowchart LR
@@ -80,22 +76,20 @@ flowchart LR
name5(Max)
```
-Konkrete Implementierungen der Schnittstelle `Queue` stellen die Klassen
-`PriorityQueue` und `LinkedList` dar. Die Klasse `PriorityQueue`
-implementiert die Warteschlange als eine Vorrang-Warteschlange. Bei einer
-Vorrang-Warteschlange werden die Elemente gemäß ihrer Wichtigkeit sortiert, das
-heißt, sie funktioniert nicht nach dem FIFO-Prinzip.
+Konkrete Implementierungen der Schnittstelle `Queue` sind `PriorityQueue`
+und `LinkedList`. Die Klasse `PriorityQueue` implementiert eine
+Vorrang-Warteschlange, bei der die Elemente nicht nach dem FIFO-Prinzip, sondern
+nach ihrer Wichtigkeit sortiert entnommen werden.
## Iteratoren
-Ein Iterator erlaubt den sequentiellen Zugriff auf die Elemente einer
-Datensammlung. Iteratoren werden durch die Schnittstelle `Iterator`
-definiert; diese bietet die Methoden `boolean hasNext()`, `E next()` und
-`void remove()`. Die von `Iterator` abgeleitete Schnittstelle
-`ListIterator` bietet zusätzliche Methoden zum Verändern einer Liste.
+Ein Iterator ermöglicht den sequentiellen Zugriff auf die Elemente einer
+Datensammlung, ohne die interne Struktur kennen zu müssen. Die Schnittstelle
+`Iterator` bietet die Methoden `boolean hasNext()`, `E next()` und
+`void remove()`.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -115,9 +109,9 @@ public class MainClass {
}
```
-Auch die bereits bekannte for-each-Schleife basiert auf Iteratoren. Die
-ausführliche Schreibeweise mit Iteratoren wird auch als erweiterte for-Schleife
-bezeichnet. Beim Kompilieren werden for-each-Schleifen um Iteratoren ergänzt.
+Auch die bereits bekannte for-each-Schleife basiert intern auf Iteratoren. Beim
+Kompilieren wird sie automatisch in eine Iterator-Schleife umgewandelt. Die
+ausführliche Schreibweise ist daher gleichwertig zur Kurzschreibweise.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -126,12 +120,13 @@ public class MainClass {
List names = List.of("Hans", "Peter", "Lisa");
+ // Ausführliche Schreibweise mit Iterator
for (Iterator iterator = names.iterator(); iterator.hasNext();) {
String name = iterator.next();
System.out.println(name);
}
- /* Kurzschreibweise */
+ // Kurzschreibweise mit for-each
for (String name : names) {
System.out.println(name);
}
diff --git a/docs/documentation/java-stream-api.md b/docs/documentation/java-stream-api.md
index 9d17c3ab08..67c36ee893 100644
--- a/docs/documentation/java-stream-api.md
+++ b/docs/documentation/java-stream-api.md
@@ -5,14 +5,12 @@ sidebar_position: 300
tags: [java-stream-api]
---
-Die Java Stream API stellt Klassen zum Erzeugen von und Arbeiten mit Strömen
-(Streams) bereit. Ein Strom stellt eine Folge von Elementen dar, die das
-Ausführen verketteter, intermediärer und terminaler Operationen auf diesen
-Elementen nacheinander oder parallel ermöglicht. Die Daten, die durch die
-Elemente des Stromes repräsentiert werden, werden dabei durch den Strom selbst
-nicht verändert. Die Verarbeitung der Elemente erfolgt nach dem Prinzip der
-Bedarfsauswertung (Lazy Evaluation). Neben endlichen Strömen stellt die Java
-Stream API auch Methoden zum Erzeugen unendlicher Ströme bereit.
+Die Java Stream API ermöglicht die funktionale Verarbeitung von Elementfolgen.
+Ein Strom (Stream) repräsentiert eine Sequenz von Elementen, auf der verkettete
+Operationen ausgeführt werden können — entweder sequentiell oder parallel. Die
+Originaldaten bleiben dabei unverändert. Die Auswertung erfolgt nach dem Prinzip
+der Bedarfsauswertung (Lazy Evaluation): Operationen werden erst dann
+ausgeführt, wenn eine terminale Operation dies erfordert.
```mermaid
flowchart TD
@@ -52,8 +50,7 @@ Ströme (Paket `java.util.stream`) haben nichts mit
## Erzeugen von Strömen
-Ströme können unter anderem aus Feldern, Datensammlungen wie z.B. Listen und
-Mengen sowie Einzelobjekten erzeugt werden.
+Ströme lassen sich aus Feldern, Listen, Mengen oder einzelnen Werten erzeugen.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -71,16 +68,16 @@ public class MainClass {
}
```
-:::info
+:::note
Die Zahlenfolge 4-8-15-16-23-42 spielt eine große Rolle in der Fernsehserie
_Lost_.
:::
-Im Gegensatz zu "normalen" Strömen besitzen Objekte der Klassen `IntStreams`,
-`DoubleStreams` und `LongStreams` Methoden zur Weiterverarbeitung ihrer
-primitiver Werte.
+Im Gegensatz zu `Stream` bieten die spezialisierten Klassen `IntStream`,
+`DoubleStream` und `LongStream` zusätzliche Methoden zur Verarbeitung primitiver
+Werte, wie etwa `sum()` oder `average()`.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -96,15 +93,16 @@ public class MainClass {
## Intermediäre Operationen
-Intermediäre Operationen ermöglichen unter anderem das Filtern, Abbilden sowie
-das Sortieren von Strömen und liefern als Ergebnis wiederum einen Strom.
+Intermediäre Operationen transformieren einen Strom in einen neuen Strom. Sie
+werden erst dann ausgeführt, wenn eine terminale Operation folgt. Typische
+intermediäre Operationen sind Filtern, Abbilden und Sortieren.
| Operation | Methode | Schnittstellen-Methode |
| ------------- | ---------------------------------------------------------- | -------------------------------- |
| Filtern | `Stream filter(predicate: Predicate)` | `boolean test(t: T)` |
| Abbilden | `Stream map(mapper: Function)` | `R apply(t: T)` |
| Abbilden | `DoubleStream mapToDouble(mapper: ToDoubleFunction)` | `double applyAsDouble(value: T)` |
-| Abbilden | `IntStream mapToInt(mapper: ToIntFunction)` | `int applyAsInt(vaue: T)` |
+| Abbilden | `IntStream mapToInt(mapper: ToIntFunction)` | `int applyAsInt(value: T)` |
| Abbilden | `LongStream mapToLong(mapper: ToLongFunction)` | `long applyAsLong(value: T)` |
| Spähen | `Stream peek(consumer: Consumer)` | `void accept(t: T)` |
| Sortieren | `Stream sorted(comparator: Comparator)` | `int compare(o1: T, o2: T)` |
@@ -114,9 +112,10 @@ das Sortieren von Strömen und liefern als Ergebnis wiederum einen Strom.
## Terminale Operationen
-Terminale Operationen werden z.B. zum Prüfen, zum Aggregieren oder zum Sammeln
-verwendet. Da terminale Operationen den Strom schließen, können auf ihnen keine
-weiteren Operationen mehr ausgeführt werden.
+Terminale Operationen schließen den Strom ab und liefern ein Ergebnis. Da der
+Strom danach nicht mehr verwendbar ist, können keine weiteren Operationen
+folgen. Typische Anwendungsfälle sind das Prüfen, Aggregieren und Sammeln von
+Elementen.
| Operation | Methode | Schnittstellen-Methode |
| ----------- | -------------------------------------------- | --------------------------- |
@@ -131,22 +130,20 @@ weiteren Operationen mehr ausgeführt werden.
| Sammeln | `R collect(collector: Collector)` | - |
| Ausführen | `void forEach(action: Consumer)` | `void accept(t: T)` |
-Zahlenströme (`IntStream`, `DoubleStream`, `LongStream`) besitzen die
-zusätzlichen terminale Operationen `int|double|long sum()` und
-`OptionalDouble average()`.
+Zahlenströme (`IntStream`, `DoubleStream`, `LongStream`) bieten zusätzlich die
+terminalen Operationen `sum()` und `average()`.
## Bedarfsauswertung (Lazy Evaluation)
-Die Elemente in Strömen werden nur bei Bedarf ausgewertet. Intermediäre
-Operationen werden also nur dann ausgeführt, wenn eine terminale Operation
-vorhanden ist und bei verketteten Operationen werden für jedes Element die
-einzelnen Operationen nacheinander ausgeführt.
+Bei der Bedarfsauswertung werden intermediäre Operationen nicht sofort
+ausgeführt, sondern erst dann, wenn eine terminale Operation den Strom
+abschließt. Zudem werden bei verketteten Operationen alle Schritte für jedes
+Element nacheinander durchlaufen — nicht erst alle Elemente durch Schritt 1,
+dann alle durch Schritt 2.
-In der main-Methode der Startklasse wird auf den Zahlenstrom 4-8-15-16-23-42
-zunächst der Filter _Zahl = ganze Zahl_ angewendet, anschließend der Filter
-_Zahl > 15_ und abschließend werden die verbliebenen Zahlen auf der Konsole
-ausgegeben. Zum Nachvollziehen werden die Zahlen auch bei den beiden Filtern auf
-der Konsole ausgegeben.
+Das folgende Beispiel filtert den Zahlenstrom 4-8-15-16-23-42 zunächst nach
+geraden Zahlen, dann nach Zahlen größer als 15, und gibt die verbliebenen Zahlen
+aus. Zur Veranschaulichung wird jeder Filterschritt ebenfalls ausgegeben.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -164,9 +161,8 @@ public class MainClass {
}
```
-Ohne Bedarfsauswertung würden die verschiedenen Operationen für die jeweils
-verbliebenen Elemente ausgeführt nacheinander werden. Die Ausgabe sähe wie folgt
-aus:
+Ohne Bedarfsauswertung würden die Operationen nacheinander für alle Elemente
+ausgeführt:
```
4: filter 1
@@ -183,9 +179,8 @@ aus:
42: forEach
```
-Aufgrund der Bedarfsauswertung werden die verschiedenen Operationen aber für
-jedes Element einzeln nacheinander ausgeführt. Dadurch ergibt sich folgende
-Ausgabe:
+Aufgrund der Bedarfsauswertung werden alle Operationen für jedes Element einzeln
+nacheinander ausgeführt:
```
4: filter 1
@@ -204,36 +199,32 @@ Ausgabe:
## Unendliche Ströme
-Die Java Stream API stellt drei Methoden zur Verfügung, mit deren Hilfe
-(un)endliche Ströme erzeugt werden können:
-
-- Die Methode `Stream iterate(seed: T, f: UnaryOperator)` generiert einen
- unendlichen Strom aus einem Startwert und einer Funktion, welche das nächste
- Element erstellt
-- Die Methode
- `Stream iterate(seed: T, hasNext: Predicat , next: UnaryOperator)`
- erweitert die "normale" iterate-Methode um eine Prädikatsfunktion zum Beenden
- des Stroms
-- Die Methode `Stream generate(s: Supplier)` kann zum Beispiel zum
- Erzeugen unendlich vieler zufälliger Elemente genutzt werden
+Die Java Stream API stellt Methoden bereit, mit denen sich theoretisch unendlich
+viele Elemente erzeugen lassen. In der Praxis werden solche Ströme durch
+`limit()` begrenzt.
-In der main-Methode der Startklasse werden drei (un)endliche Zahlenströme
-erzeugt.
+- `Stream iterate(seed: T, f: UnaryOperator)` — erzeugt einen unendlichen
+ Strom aus einem Startwert und einer Funktion, die jeweils das nächste Element
+ berechnet
+- `Stream iterate(seed: T, hasNext: Predicate, next: UnaryOperator)` —
+ wie oben, aber mit einer Abbruchbedingung
+- `Stream generate(s: Supplier)` — erzeugt Elemente über einen
+ Lieferanten, z.B. Zufallszahlen
```java title="MainClass.java" showLineNumbers
public class MainClass {
public static void main(String[] args) {
+ // Zahlen 0 bis 99 ausgeben (unendlicher Strom, begrenzt auf 100)
Stream.iterate(0, i -> ++i).limit(100).forEach(System.out::println);
+ // Zahlen 0 bis 99 mit Abbruchbedingung
Stream.iterate(0, i -> i < 100, i -> ++i).forEach(System.out::println);
+ // 100 Pseudozufallszahlen von 0 bis 99
Stream.generate(() -> new Random().nextInt(100)).limit(100).forEach(System.out::println);
}
}
```
-Die ersten beiden Zahlenströme geben die Zahlen von 0 bis 99 aus, der dritte
-Zahlenstrom 100 Pseudozufallszahlen von 0 bis 99. Der erste und dritte
-Zahlenstrom würden eigentlich unendliche viele (Pseudozufalls-)Zahlen erzeugen,
-werden aber durch die Methode `Stream limit(maxSize: long)` auf 100
-(Pseudozufalls-)Zahlen begrenzt.
+Die ersten beiden Ströme geben die Zahlen von 0 bis 99 aus. Der dritte erzeugt
+100 Pseudozufallszahlen von 0 bis 99 und wird durch `limit(100)` begrenzt.
diff --git a/docs/documentation/java.md b/docs/documentation/java.md
index 3cb0510d2e..3733ed7aea 100644
--- a/docs/documentation/java.md
+++ b/docs/documentation/java.md
@@ -6,28 +6,27 @@ tags: [java]
---
Die Programmiersprache Java gehört zu den problemorientierten
-Programmiersprachen und ist daher einfacher zu erlernen und einfacher zu
-verstehen als maschinenorientierte Programmiersprachen. Bei der Entwicklung von
-Java verfolgte man das Ziel, eine einfache, objektorientierte, robuste,
-architekturneutrale und parallelisierbare Programmiersprache zu entwickeln. Java
-wurde hauptsächlich von C und C++ beeinflusst, ist allerdings im Gegensatz zu C
-und C++ nicht darauf ausgelegt, möglichst leistungsfähige Programme zu erzeugen,
-sondern möglichst sichere und fehlerfreie Programme.
+Programmiersprachen und ist daher einfacher zu erlernen und zu verstehen als
+maschinenorientierte Sprachen. Bei der Entwicklung von Java verfolgte man das
+Ziel, eine einfache, objektorientierte, robuste, architekturneutrale und
+parallelisierbare Sprache zu schaffen. Java wurde hauptsächlich von C und C++
+beeinflusst, legt aber im Gegensatz zu diesen weniger Wert auf maximale
+Leistung, sondern vor allem auf Sicherheit und Fehlerfreiheit.
## Die Geschichte von Java
-Anfang der 90er begannen bei der Firma Sun Microsystems unter Federführung des
-Chefentwicklers James Gosling die Arbeiten an einem Projekt mit dem Codenamen
-_The Green Project_ mit dem Ziel, eine vollständige Betriebssystemumgebung für
-unterschiedliche Zwecke (interaktives Kabelfernsehen, intelligente
-Kaffeemaschinen etc.) zu entwickeln. Die daraus entstehende Programmiersprache
+Anfang der 1990er Jahre startete bei der Firma Sun Microsystems unter der
+Leitung von Chefentwickler James Gosling ein Projekt mit dem Codenamen _The
+Green Project_. Ziel war es, eine vollständige Betriebssystemumgebung für
+unterschiedliche Anwendungsfälle (interaktives Kabelfernsehen, intelligente
+Haushaltsgeräte etc.) zu entwickeln. Die daraus entstehende Programmiersprache
sollte ursprünglich den Namen _Oak_ (Object Application Kernel) tragen, wurde
-aber schließlich im Mai 1995 unter dem Namen _Java_ veröffentlicht. Der große
-Durchbruch von Java kam 1996 durch eine Kooperation mit der Firma Netscape
-zustande, die eine Integration von Java-Applets mit Hilfe von JavaScript in den
-Browser Netscape Navigator 2.0 ermöglichte. Weitere wichtige Meilensteine in der
-Geschichte von Java waren die Veröffentlichungen der Google-Entwicklungsumgebung
-Android 2008 sowie des Computerspiels Minecraft 2009.
+aber schließlich im Mai 1995 unter dem Namen _Java_ veröffentlicht. Der
+Durchbruch gelang 1996 durch eine Kooperation mit der Firma Netscape, die eine
+Integration von Java-Applets in den Browser Netscape Navigator 2.0 ermöglichte.
+Weitere wichtige Meilensteine waren die Veröffentlichung der
+Android-Entwicklungsumgebung von Google (2008) sowie des Computerspiels
+Minecraft (2009).
:::info
@@ -37,43 +36,40 @@ Java war der Name der beliebtesten Kaffeesorte der Entwickler.
## JDK und JRE
-Das JDK (Java Development Kit) stellt die wichtigste Komponente zum
-Programmieren von Java-Programmen dar. Es enthält neben dem Compiler und
-Debugger weitere wichtige Werkzeuge sowie umfangreiche Bibliotheken (siehe
-[Die Java API](java-api)). Die JRE (Java Runtime Environment) enthält den
-Interpreter (die _Java Virtual Machine_) und wird zum Ausführen von
-Java-Applikationen benötigt. Seit September 2017 wird alle sechs Monate eine
-neue JDK-Version veröffentlicht (i.d.R. Mitte März und Mitte September eines
-Jahres). Diese Versionen werden von Oracle nur bis zum Erscheinen der jeweils
-nächsten Version unterstützt. Eine Ausnahme bilden hier die LTS-Versionen
-(long-term-support-releases). Die aktuellen LTS-Versionen sind 8, 11, 17 und 21.
+Das _Java Development Kit_ (JDK) ist die wichtigste Komponente zur Entwicklung
+von Java-Programmen. Es enthält neben dem Compiler und Debugger weitere
+Werkzeuge sowie umfangreiche Bibliotheken (siehe [Die Java API](java-api)). Die
+_Java Runtime Environment_ (JRE) enthält den Interpreter (die _Java Virtual
+Machine_) und wird zum Ausführen von Java-Programmen benötigt. Seit September
+2017 erscheint alle sechs Monate eine neue JDK-Version (in der Regel Mitte März
+und Mitte September). Diese Versionen werden von Oracle nur bis zum Erscheinen
+der jeweils nächsten Version unterstützt. Eine Ausnahme bilden die LTS-Versionen
+(Long-Term-Support-Releases). Die aktuellen LTS-Versionen sind 8, 11, 17 und 21.
Die Neuerungen einer Version werden durch sogenannte JEPs (JDK Enhancement
Proposals) festgelegt. Weitere Informationen zu den verschiedenen JDK-Versionen
-können auf der offziellen [JDK-Seite](https://jdk.java.net/) gefunden werden.
+sind auf der offiziellen [JDK-Seite](https://jdk.java.net/) zu finden.
## Entwicklung von Java-Programmen
-Zur Entwicklung von Java-Programmen wird neben dem _Java Development Kit_ (JDK)
-nur ein einfacher Texteditor benötigt. Das Kompilieren und Ausführen der Klassen
-erfolgt dann über die Kommandozeile (Command Line Interface, kurz CLI).
-Alternativ kann auch eine Entwicklungsumgebung (Integrated Development
-Environment, kurz IDE) verwendet werden. Diese bieten in der Regel zusätzliche
-Komfortfunktionen wie Syntaxhighlighting, Autovervollständigung,
-Vorschlagslisten etc. und vereinfachen so die Entwicklung von Programmen. Die am
-weitesten verbreiteten Entwicklungsumgebungen im Java-Umfeld sind dabei
-[IntelliJ IDEA](https://www.jetbrains.com/idea/) und
+Zur Entwicklung von Java-Programmen wird neben dem JDK nur ein einfacher
+Texteditor benötigt. Das Kompilieren und Ausführen erfolgt dann über die
+Kommandozeile (Command Line Interface, kurz CLI). Alternativ kann eine
+Entwicklungsumgebung (Integrated Development Environment, kurz IDE) verwendet
+werden. Diese bietet in der Regel zusätzliche Komfortfunktionen wie
+Syntaxhervorhebung, Autovervollständigung und Vorschlagslisten, was die
+Entwicklung deutlich erleichtert. Die am weitesten verbreiteten IDEs im
+Java-Umfeld sind [IntelliJ IDEA](https://www.jetbrains.com/idea/) und
[Eclipse IDE](https://www.eclipse.org/).
## Programmierstil (Code Style)
Als Programmierstil (Code Style) bezeichnet man alle Regeln und Richtlinien, die
-Entwickler befolgen sollten, um sicherzustellen, dass ihr Quellcode konsistent,
-gut lesbar und leicht wartbar ist. Ein einheitlicher Programmierstil erleichtert
-so auch die Zusammenarbeit in Teams, da er die Verständlichkeit und Wartbarkeit
-des Codes verbessert.
+Entwicklerinnen und Entwickler befolgen sollten, um sicherzustellen, dass ihr
+Quellcode konsistent, gut lesbar und leicht wartbar ist. Ein einheitlicher
+Programmierstil erleichtert auch die Zusammenarbeit in Teams, da er die
+Verständlichkeit und Wartbarkeit des Codes verbessert.
-Ein Programmierstil legt unter anderem Regeln und Richtlinien für nachfolgende
-Aspekte fest:
+Ein Programmierstil legt unter anderem Regeln für folgende Aspekte fest:
- Namenskonventionen
- Klammersetzung
@@ -87,11 +83,11 @@ Zu den bekanntesten Programmierstilen in Java gehören die offiziellen
[Code Conventions for the Java Programming Language](https://www.oracle.com/java/technologies/javase/codeconventions-introduction.html)
von Oracle sowie der
[Google Java Style](https://google.github.io/styleguide/javaguide.html) von
-Google. Zudem existiert mit
+Google. Zudem gibt es mit
[Prettier Java](https://github.com/jhipster/prettier-java) eine Erweiterung für
-den weit verbreiteten Code Formatierer [Prettier](https://prettier.io/). Neben
-vielen Gemeinsamkeiten wie dem Verzicht auf Tabulatorspürunge zur Einrückung,
-den Regeln zu Leerzeichen sowie zur Klammersetzung unterscheiden sich die
-genannten Programmierstile aber auch in Regeln wie der Anzahl der Leerzeichen
-zur Einrückung, der festgelegten Zeilenlänge sowie dem Umgang mit
-Zeilenumbrüchen bei funktionalen Aufrufen.
+den weit verbreiteten Code-Formatierer [Prettier](https://prettier.io/). Neben
+vielen Gemeinsamkeiten — etwa dem Verzicht auf Tabulatorzeichen zur Einrückung,
+den Regeln zu Leerzeichen sowie zur Klammersetzung — unterscheiden sich die
+genannten Stile in Details wie der Anzahl der Leerzeichen zur Einrückung, der
+festgelegten Zeilenlänge sowie dem Umgang mit Zeilenumbrüchen bei funktionalen
+Aufrufen.
diff --git a/docs/documentation/javafx.mdx b/docs/documentation/javafx.mdx
index 605587c316..570e92f851 100644
--- a/docs/documentation/javafx.mdx
+++ b/docs/documentation/javafx.mdx
@@ -8,18 +8,13 @@ tags: [gui, javafx]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Java stellt mit dem _AWT_ (Abstract Window Toolkit) und _Swing_ zwei
-Bibliotheken zur Entwicklung grafischer Benutzeroberflächen zur Verfügung. Swing
-baut dabei auf dem älteren AWT auf und verwendet teilweise Klasse daraus. Der
-Nachfolger von Swing heißt JavaFX und stellt im Gegensatz zu AWT und Swing keine
-Bibliothek, sondern ein Framework zur Entwicklung plattformübergreifender
-grafischer Benutzeroberflächen dar. Unter einem Framework versteht man ein
-Programmiergerüst, welches die Architektur für die Anwendung vorgibt und den
-Kontrollfluss der Anwendung steuert. So werden die Funktionen einer Anwendung
-beim Framework registriert, welches die Funktionen zu einem späteren Zeitpunkt
-aufruft, d.h. die Steuerung des Kontrollfluss obliegt nicht der Anwendung,
-sondern dem Framework. Diese Umkehr der Steuerung kann auch als Anwendung des
-Hollywood-Prinzips (_Don´t call us, we´ll call you_) verstanden werden.
+Java bietet mit _AWT_ (Abstract Window Toolkit) und _Swing_ zwei ältere
+Bibliotheken für grafische Benutzeroberflächen. Der Nachfolger beider ist
+_JavaFX_ — ein Framework für plattformübergreifende GUIs. Als Framework gibt
+JavaFX die Architektur vor und steuert den Kontrollfluss nach dem Prinzip der
+_Inversion of Control_: Statt dass die Anwendung JavaFX aufruft, registriert sie
+ihre Funktionen beim Framework, das sie dann aufruft — das sogenannte
+Hollywood-Prinzip: _Don't call us, we'll call you_.
:::info
@@ -30,11 +25,10 @@ eigenständiges SDK (Software Development Kit) dar.
## Aufbau und Lebenszyklus von JavaFX-Anwendungen
-JavaFX-Anwendungen bestehen aus einer oder mehreren Bühnen (Stages), die
-beliebig vielen Szenen (Scenes) enthalten können, wobei jede Szene wiederum
-beliebig viele Bildschirmelemente (Nodes) enthalten kann. Jede JavaFX-Anwendung
-ist eine Unterklasse der Klasse `Application`. Diese stellt die verschiedenen
-Lebenszyklus-Methoden der JavaFX-Anwendung bereit.
+Eine JavaFX-Anwendung besteht aus Bühnen (Stages), die Szenen (Scenes)
+enthalten, die wiederum Bildschirmelemente (Nodes) beinhalten. Jede
+JavaFX-Anwendung erbt von der Klasse `Application`, die den Lebenszyklus
+verwaltet:
- Die Methode `void launch(args: String[])` speichert die Aufrufparameter,
erzeugt ein Objekt der eigenen Klasse und ruft die weiteren
@@ -48,14 +42,12 @@ Lebenszyklus-Methoden der JavaFX-Anwendung bereit.
## Definition von Szenen
-Die Definition einer Szene (View) kann entweder objektorientiert oder deklarativ
-mit Hilfe von FXML-Dokumenten erfolgen. FXML stellt eine auf XML-basierende
-Sprache dar und ermöglicht eine klare Trennung zwischen Layout und Code. XML
-(Extensible Markup Language) wiederum stellt eine Auszeichnungssprache zur
-Beschreibung strukturierter Daten dar.
+Eine Szene (View) kann objektorientiert im Code oder deklarativ mit
+FXML-Dokumenten definiert werden. FXML ist eine XML-basierte
+Beschreibungssprache, die eine klare Trennung zwischen Layout und Code
+ermöglicht.
-Mit Hilfe spezifischer JavaFX-Eigenschaften wird eine Verbindung zwischen der
-Szene und der Ereignisbehandler-Klasse hergestellt:
+JavaFX-spezifische Eigenschaften verknüpfen Szene und Controller:
- Bildschirmelementen können über die Eigenschaft `fx:id` IDs zugewiesen werden,
über die die Ereignisbehandler-Klasse auf die jeweiligen Elemente zugreifen
@@ -115,14 +107,10 @@ Szene und der Ereignisbehandler-Klasse hergestellt:
## Aufruf von Szenen
-Die statische Methode `Parent load(location: URL)` der Klasse `FXMLLoader`
-überführt das angegebene FXML-Dokument in einen Szenegraphen und gibt den
-dazugehörigen Wurzelknoten vom Typ `Parent` zurück, mit dessen Hilfe
-anschließend die Szene erstellt und angezeigt werden kann. Zusätzlich
-instanziiert der FXML-Loader den Controller und ruft bei der Anzeige der Szene
-die (optionale) Methode
-`void initialize(location: URL, resources: ResourceBundle)` der entsprechenden
-Ereignisbehandler-Klasse auf.
+Die Methode `Parent load(location: URL)` der Klasse `FXMLLoader` lädt ein
+FXML-Dokument, erstellt den Szenegraphen und gibt den Wurzelknoten zurück. Der
+FXML-Loader instanziiert dabei automatisch den Controller und ruft bei Anzeige
+der Szene dessen `initialize()`-Methode auf.
```java title="MainClass.java" showLineNumbers
public class MainClass extends Application {
@@ -145,20 +133,14 @@ public class MainClass extends Application {
## Implementierung von Ereignisbehandler-Klassen
-In den Ereignisbehandler-Klassen (Controller) werden die Behandlermethoden
-implementiert. Diese müssen zwingend einen Parameter vom Typ des Ereignisses
-besitzen (z.B. `ActionEvent`), mit dessen Hilfe auf das ausgelöste Ereignis
-zugegriffen werden kann. Das Verknüpfen von Attributen der
-Ereignisbehandler-Klasse mit den Elementen des FXML-Dokuments erfolgt über die
-Annotation `@FXML` und der Namensgleichheit zwischen den Attributen der
-Ereignisbehandler-Klasse sowie den festgelegten Ids der entsprechenden Elemente
-des FXML-Dokuments.
-
-Der Wechsel von Szenen erfolgt über die Methode `void setScene(value: Scene)`
-der Klasse `Window`. Die Methode `Object getSource()` der Klasse `ActionEvent`
-gibt das Bildschirmelement zurück, welches das Ereignis ausgelöst hat; die
-Methode `Window getWindow()` der Klasse `Scene` die Bühne, auf der die aktuelle
-Szene aufgeführt wird.
+In den Controller-Klassen werden die Behandlermethoden implementiert. Jede
+Behandlermethode muss einen Parameter vom Typ des Ereignisses besitzen (z.B.
+`ActionEvent`). Die Verknüpfung von Attributen der Controller-Klasse mit
+FXML-Elementen erfolgt über die Annotation `@FXML` und übereinstimmende Namen
+zwischen Attributen und `fx:id`-Werten im FXML-Dokument.
+
+Der Szenenwechsel erfolgt über `void setScene(value: Scene)` der Klasse
+`Window`.
@@ -225,10 +207,9 @@ Szene aufgerufen und ermöglicht es, die Szene dynamisch anzupassen.
## Implementierung von Model-Klassen
-Model-Klassen sind für die zentrale Verwaltung der Daten zuständig. Da die
-verschiedenen Klassen einer JavaFX-Anwendung nur lose miteiander gekoppelt sind,
-kann über das Entwurfsmuster _Singleton_ sichergestellt werden, dass zur
-Model-Klasse genau ein Objekt, das sogenannte Singleton, zur Laufzeit existiert.
+Model-Klassen verwalten die Anwendungsdaten zentral. Da die Klassen einer
+JavaFX-Anwendung nur lose gekoppelt sind, sorgt das Entwurfsmuster _Singleton_
+dafür, dass zur Laufzeit genau ein Model-Objekt existiert.
```java title="Model.java" showLineNumbers
public class Model {
diff --git a/docs/documentation/lambdas.md b/docs/documentation/lambdas.md
index 89f6d73232..d2a66aee60 100644
--- a/docs/documentation/lambdas.md
+++ b/docs/documentation/lambdas.md
@@ -5,13 +5,13 @@ sidebar_position: 265
tags: [inner-classes, lambdas]
---
-Lambda-Ausdrücke sind anonyme Funktionen, die nur über ihre Referenz
-angesprochen werden können.
+Lambda-Ausdrücke sind anonyme Funktionen, die einer Variablen zugewiesen oder
+direkt als Parameter übergeben werden können.
## Implementierung von Lambda-Ausdrücken
-Die Methodenparameter sowie der Methodenkörper werden bei einem Lambda-Ausdruck
-getrennt vom Pfeiloperator `->` notiert.
+Die Parameterliste und der Methodenkörper eines Lambda-Ausdrucks werden durch
+den Pfeiloperator `->` getrennt.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -31,29 +31,28 @@ public class MainClass {
:::info
-Voraussetzung für den Einsatz eines Lambda-Ausdrucks ist eine funktionale
-Schnittstelle, also eine Schnittstelle, die über genau eine Methode verfügt.
+Voraussetzung für Lambda-Ausdrücke ist eine _funktionale Schnittstelle_ — eine
+Schnittstelle mit genau einer abstrakten Methode.
:::
## Syntaxvarianten
-- Bei keinem oder mehreren Methodenparametern müssen diese in runden Klammern
- angegeben werden, bei genau einem Methodenparameter können die runden Klammern
- weggelassen werden
-- Besteht der Methodenkörper aus mehreren Anweisungen, müssen diese in
- geschweiften Klammern angegeben werden, bei genau einer Anweisung können die
- geschweiften Klammern weggelassen werden
-- Besteht der Methodenkörper aus genau einer Anweisung, kann das Semikolon am
- Anweisungsende weggelassen werden, ist die Anweisung eine return-Anweisung,
- kann auch das `return` weggelassen werden
+Die Syntax von Lambda-Ausdrücken erlaubt verschiedene Kurzformen:
+
+- Enthält die Parameterliste genau einen Parameter, können die runden Klammern
+ weggelassen werden; bei keinem oder mehreren Parametern sind sie verpflichtend
+- Besteht der Methodenkörper aus genau einer Anweisung, können die geschweiften
+ Klammern und das abschließende Semikolon weggelassen werden
+- Besteht diese eine Anweisung aus einer `return`-Anweisung, kann auch das
+ Schlüsselwort `return` weggelassen werden
## Methodenreferenzen
-Lambda-Ausdrücke, die nur aus dem Aufruf einer Methode bestehen, können als
-Methodenreferenz dargestellt werden. Bei einer Methodenreferenz wird die Klasse
-bzw. die Referenz auf der linken Seite mit Hilfe zweier Doppelpunkte vom
-Methodennamen auf der recht Seite getrennt.
+Besteht ein Lambda-Ausdruck ausschließlich aus dem Aufruf einer Methode, kann er
+als _Methodenreferenz_ geschrieben werden. Die Klasse oder Referenz auf der
+linken Seite wird dabei durch `::` vom Methodennamen auf der rechten Seite
+getrennt.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/lists.mdx b/docs/documentation/lists.mdx
index 7d0701cc1d..4baef83eb0 100644
--- a/docs/documentation/lists.mdx
+++ b/docs/documentation/lists.mdx
@@ -2,24 +2,23 @@
title: Listen
description: ''
sidebar_position: 215
-tags: [collections, namess]
+tags: [collections, lists]
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Die Java API stellt unter Anderem die Schnittstelle `List` sowie die Klassen
-`ArrayList`, `LinkedList` und `Arrays` zur Verfügung, mit deren Hilfe
-Listen realisiert werden. Unter einer Liste versteht man eine geordnete Folge
-von Elementen, die auch doppelt enthalten sein können. Der Zugriff auf die
-Elemente erfolgt über den Index oder sequentiell.
+Eine Liste ist eine geordnete Folge von Elementen, die auch doppelte Einträge
+enthalten kann. Der Zugriff erfolgt über den Index oder sequentiell. Die Java
+API stellt dafür die Schnittstelle `List` sowie die Klassen `ArrayList`,
+`LinkedList` und `Arrays` bereit.
-Die Schnittstelle `List` bietet verschiedene Fabrikmethoden zum Erzeugen
-unveränderbarer Listen. Unveränderbar bedeutet, dass weder die Liste selbst noch
-ihre Elemente geändert werden können.
+Die Schnittstelle `List` bietet Fabrikmethoden zum Erzeugen unveränderlicher
+Listen. Unveränderbar bedeutet, dass weder Elemente hinzugefügt, entfernt noch
+ersetzt werden können.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -29,9 +28,9 @@ public class MainClass {
System.out.println(names.size());
System.out.println(names.get(0));
- names.set(0, "Max"); // Laufzeitfehler
- names.add("Heidi"); // Laufzeitfehler
- names.remove(0); // Laufzeitfehler
+ names.set(0, "Max"); // Laufzeitfehler: Liste ist unveränderbar
+ names.add("Heidi"); // Laufzeitfehler: Liste ist unveränderbar
+ names.remove(0); // Laufzeitfehler: Liste ist unveränderbar
}
}
@@ -46,9 +45,10 @@ Fabrikmethoden sind Methoden, die Objekte erzeugen.
-Die Klasse `Arrays` stellt neben Methoden zum Sortieren und Durchsuchen von
-Feldern auch eine Methode zum Erzeugen veränderbarer Listen fixer Größe zur
-Verfügung.
+Die Klasse `Arrays` bietet neben Methoden zum Sortieren und Durchsuchen von
+Feldern auch eine Methode zum Erzeugen veränderbarer Listen fixer Größe. Die
+Anzahl der Elemente ist dabei festgelegt; einzelne Elemente lassen sich jedoch
+ersetzen.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -58,9 +58,9 @@ public class MainClass {
System.out.println(names.size());
System.out.println(names.get(0));
- names.set(0, "Max");
- names.add("Heidi"); // Laufzeitfehler
- names.remove(0); // Laufzeitfehler
+ names.set(0, "Max"); // Element ersetzen ist erlaubt
+ names.add("Heidi"); // Laufzeitfehler: Größe ist fest
+ names.remove(0); // Laufzeitfehler: Größe ist fest
}
}
@@ -69,15 +69,16 @@ public class MainClass {
-Die Klasse `ArrayList` stellt eine veränderbare Liste dynamischer Größe auf
-Basis eine Feldes dar, die Klasse `LinkedList` eine veränderbare Liste
-dynamischer Größe auf Basis doppelt verketteter Elemente.
+Die Klasse `ArrayList` implementiert eine veränderbare Liste auf Basis eines
+Feldes, die Klasse `LinkedList` auf Basis doppelt verketteter Knoten. Beide
+unterstützen das Hinzufügen, Ersetzen und Entfernen von Elementen sowie eine
+dynamische Größe.
```java title="MainClass.java" showLineNumbers
public class MainClass {
public static void main(String[] args) {
- List names = new ArrayList<>(); // = new LinkedList<>();
+ List names = new ArrayList<>(); // alternativ: new LinkedList<>()
names.add("Hans");
names.add("Peter");
names.add("Lisa");
@@ -94,9 +95,10 @@ public class MainClass {
:::info
-Eine feldbasierte Liste ist bei wahlfreiem Zugriff schneller als eine verkettete
-Liste; eine verkettete Liste ist bei Anfüge- und Löschoperationen (insbesondere
-bei großen Elementzahlen) schneller als eine feldbasierte Liste.
+Eine feldbasierte Liste (`ArrayList`) ist bei wahlfreiem Zugriff über den Index
+schneller. Eine verkettete Liste (`LinkedList`) ist bei Einfüge- und
+Löschoperationen in der Mitte der Liste schneller, da keine Elemente verschoben
+werden müssen.
:::
diff --git a/docs/documentation/lombok.mdx b/docs/documentation/lombok.mdx
index ddf8439317..23268630b7 100644
--- a/docs/documentation/lombok.mdx
+++ b/docs/documentation/lombok.mdx
@@ -8,15 +8,14 @@ tags: [lombok]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-[Lombok](https://projectlombok.org/) stellt eine externe Java-Bibliothek dar,
-die das Erstellen von Boilerplate-Code überflüssig macht. Repetitive Methoden
-wie Konstruktoren, Getter, Setter und die Objekt-Methoden müssen nicht manuell
-implementiert werden, sondern werden beim Kompilieren generiert.
+[Lombok](https://projectlombok.org/) ist eine externe Java-Bibliothek, die
+wiederkehrenden Boilerplate-Code automatisch generiert. Konstruktoren, Getter,
+Setter und die `Object`-Methoden werden nicht manuell geschrieben, sondern beim
+Kompilieren durch Annotationen erzeugt.
## Annotationen
-Durch entsprechende Annotationen kann gesteuert werden, welche Methoden wie
-generiert werden sollen.
+Über Annotationen wird gesteuert, welche Methoden Lombok generieren soll.
| Annotation | Beschreibung |
| -------------------------- | -------------------------------------------------------------------------------------------------- |
@@ -30,8 +29,9 @@ generiert werden sollen.
## Beispiel
-Für die Klasse `Student` werden mit Hilfe von Lombok-Annotationen Konstruktoren,
-Setter und Getter sowie die Object-Methoden generiert.
+Die Klasse `Student` wird mit Lombok-Annotationen versehen, sodass
+Konstruktoren, Getter, Setter und die `Object`-Methoden automatisch generiert
+werden.
diff --git a/docs/documentation/loops.md b/docs/documentation/loops.md
index 7a8964620d..522caf823c 100644
--- a/docs/documentation/loops.md
+++ b/docs/documentation/loops.md
@@ -5,16 +5,15 @@ sidebar_position: 105
tags: [control-structures, loops]
---
-Schleifen sind eine von zwei Möglichkeiten, Anweisungsblöcke wiederholt
-auszuführen. Die zweite Möglichkeit sind Selbstaufrufe in Form rekursiver
-Methoden.
+Schleifen sind eine Möglichkeit, Anweisungsblöcke wiederholt auszuführen. Eine
+weitere Möglichkeit sind rekursive Methoden, die sich selbst aufrufen.
## while-Schleifen
-Bei der while-Schleife wird eine bestimmte Anweisungsfolge (_Schleifenrumpf_)
-wiederholt, solange eine bestimmte Bedingung (_Schleifenbedingung_) wahr ist. Da
-zu Beginn der Schleife die Bedingung geprüft wird, spricht man auch von einer
-_kopfgesteuerten Schleife_.
+Bei der while-Schleife wird ein Anweisungsblock (_Schleifenrumpf_) wiederholt,
+solange eine Bedingung (_Schleifenbedingung_) wahr ist. Da die Bedingung zu
+Beginn jedes Durchlaufs geprüft wird, spricht man von einer _kopfgesteuerten
+Schleife_.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -33,8 +32,8 @@ public class MainClass {
## do/while-Schleifen
Im Gegensatz zur while-Schleife wird bei der do/while-Schleife der
-Schleifenrumpf immer mindestens einmal durchlaufen. Da die Bedingung hier am
-Ende der Schleife geprüft wird, spricht man hier von einer _fußgesteuerten
+Schleifenrumpf immer mindestens einmal ausgeführt, da die Bedingung erst am Ende
+des Durchlaufs geprüft wird. Daher spricht man von einer _fußgesteuerten
Schleife_.
```java title="MainClass.java" showLineNumbers
@@ -53,9 +52,8 @@ public class MainClass {
## for-Schleifen
-Bei der for-Schleife handelt es sich um eine indexgesteuerte Schleife, auch
-_Zählschleife_ genannt. Durch den Index wird bereits zu Schleifenbeginn
-festgelegt, wie oft die Schleife durchlaufen wird.
+Die for-Schleife ist eine indexgesteuerte Schleife, auch _Zählschleife_ genannt.
+Der Index legt bereits zu Beginn fest, wie oft die Schleife durchlaufen wird.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -71,10 +69,10 @@ public class MainClass {
## for-each-Schleifen
-Mit Hilfe der for-each-Schleife können Datensammlungen wie z.B. [Felder](arrays)
-und [Listen](lists) elementweise durchlaufen werden. Allerdings können die
-Elemente einer Datensammlung nur geändert werden, nicht jedoch die Datensammlung
-selbst.
+Mit der for-each-Schleife können Datensammlungen wie [Felder](arrays) und
+[Listen](lists) elementweise durchlaufen werden. Dabei können einzelne Elemente
+verändert werden, jedoch nicht die Struktur der Sammlung selbst (z.B. kein
+Hinzufügen oder Entfernen von Elementen).
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -91,10 +89,9 @@ public class MainClass {
## Schleifensteuerung
-Die Anweisung `break` sorgt dafür, dass eine Schleife ungeachtet der Bedingung
-komplett verlassen wird. Mit der Anweisung `continue` wird der aktuelle
-Schleifendurchgang abgebrochen und die Schleife wird mit dem nächsten Durchlauf
-fortgeführt.
+Mit `break` wird eine Schleife unabhängig von der Bedingung sofort beendet. Mit
+`continue` wird der aktuelle Schleifendurchgang abgebrochen und die Schleife mit
+dem nächsten Durchlauf fortgesetzt.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/maps.md b/docs/documentation/maps.md
index 3d9bf6a240..641b6664d2 100644
--- a/docs/documentation/maps.md
+++ b/docs/documentation/maps.md
@@ -5,11 +5,9 @@ sidebar_position: 280
tags: [maps]
---
-Unter einem Assoziativspeicher (Map) versteht man eine Menge zusammengehöriger
-Paare von Objekten. Das erste Objekt stellt dabei den Schlüssel (Key), das
-zweite Objekt den Wert (Value) dar. Jeder Schlüssel kann dabei nur einmal in
-einem Assoziativspeicher vorhanden sein. Aufgrund dieses Aufbaus werden
-Assoziativspeicher auch als Wörterbücher bezeichnet.
+Ein Assoziativspeicher (Map) ist eine Sammlung von Schlüssel-Wert-Paaren. Jeder
+Schlüssel (Key) ist eindeutig und verweist auf genau einen Wert (Value). Wegen
+dieser Struktur werden Assoziativspeicher auch als _Wörterbücher_ bezeichnet.
```mermaid
flowchart LR
@@ -22,10 +20,9 @@ flowchart LR
end
```
-Um auf die Einträge, Schlüssel und Werte eines Assoziativspeichers zugreifen
-können, stellt die Schnittstelle `Map` die Methoden
-`Set> entrySet()`, `Set keySet()` und `Collection values()`
-zur Verfügung.
+Für den Zugriff auf Einträge, Schlüssel und Werte eines Assoziativspeichers
+stellt die Schnittstelle `Map` die Methoden `Set> entrySet()`,
+`Set keySet()` und `Collection values()` bereit.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -55,12 +52,10 @@ public class MainClass {
}
```
-Die Klasse `HashMap` implementiert den Assoziativspeicher in Form einer
-Hashtabelle. Für den Einsatz einer Hashtabelle ist es zwingend erforderlich,
-dass die Klasse, die den Schlüssel bildet, die Methoden `int hashCode()` und
-`boolean equals(object: Object)` gemäß den entsprechenden
-Dokumentationskommentaren überschrieben hat. Im Gegensatz zu einem Binärbaum
-liegen die Paare in einer Hashtabelle unsortiert vor.
+Die Klasse `HashMap` implementiert den Assoziativspeicher als Hashtabelle.
+Voraussetzung ist, dass die Schlüsselklasse die Methoden `int hashCode()` und
+`boolean equals(object: Object)` korrekt überschrieben hat. Die Einträge liegen
+in einer Hashtabelle unsortiert vor.
| Index | Schlüssel | Wert |
| ----- | --------- | ---- |
@@ -69,14 +64,12 @@ liegen die Paare in einer Hashtabelle unsortiert vor.
| 13 | Lisa | 1.8 |
| 14 | Max | 4.2 |
-Die Klasse `TreeMap` implementiert den Assoziativspeicher in Form eines
-Binärbaumes. Als Datenstruktur wird dabei ein balancierter Baum verwendet, d.h.
-spezielle Einfüge- und Löschoperationen stellen sicher, dass der Baum nicht zu
-einer linearen Liste entartet. Da die Paare in einem Binärbaum sortiert
-vorliegen, ist es für den Einsatz zwingend erforderlich, dass die Klasse, die
-den Schlüssel bildet, die Schnittstelle `Comparable` implementiert hat.
-Alternativ kann dem Konstruktor der Klasse `TreeMap` ein Komparator für
-den Schlüssel mitgegeben werden.
+Die Klasse `TreeMap` implementiert den Assoziativspeicher als Binärbaum.
+Dabei wird ein balancierter Baum verwendet, sodass spezielle Einfüge- und
+Löschoperationen sicherstellen, dass der Baum nicht zu einer linearen Liste
+entartet. Die Einträge liegen sortiert vor, weshalb die Schlüsselklasse die
+Schnittstelle `Comparable` implementieren oder dem Konstruktor ein
+`Comparator` übergeben werden muss.
```mermaid
flowchart TD
diff --git a/docs/documentation/mockito.mdx b/docs/documentation/mockito.mdx
index 1b36eb37c9..4c8c411ee6 100644
--- a/docs/documentation/mockito.mdx
+++ b/docs/documentation/mockito.mdx
@@ -8,68 +8,50 @@ tags: [mockito]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-[Mockito](https://site.mockito.org/) ist ein leistungsfähiges und einfach zu
-verwendendes Framework für das Erstellen von Mock-Objekten in Java. Mock-Objekte
-simulieren das Verhalten realer Komponenten und werden oft in Tests anstelle der
-realen Komponenten verwendet. Durch den Einsatz von Mock-Objekten werden die
-Abhängigkeiten des SUT (System under Test) minimiert und so das Testen von
-Anwendungen erheblich vereinfacht. Man spricht in diesem Zusammenhang auch von
-der sogenannten Test-Isolierung. Gründe für den Einsatz von Mock-Objekten können
-komplexe Abhängigkeiten, ungewünschte Seiteneffekte oder hohe Laufzeiten der
-realen Komponenten sein.
+[Mockito](https://site.mockito.org/) ist ein Framework für das Erstellen von
+Mock-Objekten in Java. Mock-Objekte simulieren das Verhalten realer Komponenten
+und ersetzen diese in Tests. Dadurch werden Abhängigkeiten des SUT (System under
+Test) reduziert und die Tests isoliert (Test-Isolierung). Typische Gründe für
+Mock-Objekte sind komplexe Abhängigkeiten, unerwünschte Seiteneffekte oder hohe
+Laufzeiten realer Komponenten.
## Arten von Mock-Objekten
-Man unterscheidet zwischen verschiedenen Arten von Mock-Objekten.
+Mockito unterscheidet zwischen drei Arten von Testobjekten:
-- Ein _Stub_ ist ein Objekt, welches beim Aufruf einer Methode unabhängig der
- Eingabe immer den selben festgelegten Wert zurückgibt
-- Ein _Mock_ ist ein Objekt, welches im Gegensatz zum Stub beim Aufruf einer
- Methode abhängig von der Eingabe festgelegte Werte zurückgibt
-- Ein _Spy_ ist ein Objekt, welches Aufrufe und übergebene Werte protokolliert
- und abfragbar macht
+- Ein _Stub_ gibt unabhängig von der Eingabe immer denselben festgelegten Wert
+ zurück.
+- Ein _Mock_ gibt abhängig von der Eingabe unterschiedliche festgelegte Werte
+ zurück.
+- Ein _Spy_ protokolliert Methodenaufrufe und die übergebenen Argumente, sodass
+ sie im Test abgefragt werden können.
## Simulieren von Objekten
-Mockito stellt für das Erzeugen von Mock-Objekten zum Einen die statische
-Methode `T mock(reified: T...)` der Klasse `Mockito` und zum Anderen die
-Annotation `@Mock` sowie die statische Methode
-`AutoCloseable openMocks(testClass: Object)` der Klasse `MockitoAnnotations` zur
-Verfügung. In beiden Fällen wird ein entsprechendes Objekt der angegebenen
-Klasse erstellt, allerdings ohne jegliche Methodenimplementierungen. Das
-Verhalten einzelner Methoden kann anschließend über die statische Methode
-`OngoingStubbing when(methodCall: T)` der Klasse `Mockito` sowie über die
-Methode `OngoingStubbing thenReturn(value: T)` bzw.
-`OngoingStubbing thenThrow(throwables: Throwable...)` der Klasse
-`OngoingStubbing` festgelegt werden.
+Mock-Objekte werden entweder mit der statischen Methode `T mock(reified: T...)`
+der Klasse `Mockito` oder mit der Annotation `@Mock` in Verbindung mit
+`MockitoAnnotations.openMocks()` erstellt. Ein so erzeugtes Objekt hat keine
+Methodenimplementierungen. Das gewünschte Verhalten wird über
+`Mockito.when(...).thenReturn(...)` bzw. `.thenThrow(...)` festgelegt.
## Umhüllen von Objekten
-Für das Erzeugen von Spy-Objekten stellt Mockito zum Einen die statische Methode
-`T spy(object: T)` der Klasse `Mockito` und zum Anderen die Annotation `@Spy`
-sowie die statische Methode `AutoCloseable openMocks(testClass: Object)` der
-Klasse `MockitoAnnotations` zur Verfügung. Durch das so umhüllte Objekt kann das
-Verhalten einzelner Methoden anschließend über die statische Methode
-`Stubber doReturn(toBeReturned: Object)` bzw.
-`Stubber doThrow(toBeThrown: Throwable...)` der Klasse `Mockito` sowie über die
-Methode `T when(mock: T)` der Klasse `Stubber` überschrieben werden.
+Spy-Objekte werden mit `T spy(object: T)` der Klasse `Mockito` oder mit der
+Annotation `@Spy` erstellt. Im Gegensatz zum Mock delegiert ein Spy
+standardmäßig an die echte Implementierung. Einzelne Methoden können mit
+`Mockito.doReturn(...).when(...)` überschrieben werden.
## Prüfen von Methodenaufrufen
-Für das Prüfen, ob, wie oft und in welcher Reihenfolge eine Methode eines
-Mock-Objektes aufgerufen wurde, stellt Mockito die statische Methode
-`T verify(mock: T, mode: VerificationMode)` der Klasse `Mockito` zur Verfügung.
-Zur Angabe des Prüfungsmodus können die statischen Methoden
-`VerificationMode times(wantedNumberOfInvocations: int)`,
-`VerificationMode atLeast(minNumberOfInvocations: int)`,
-`VerificationMode atMost(maxNumberOfInvocations: int)` und
-`VerificationMode never()` der Klasse `Mockito` verwendet werden.
+Mit `Mockito.verify(mock, mode)` wird geprüft, ob und wie oft eine Methode
+aufgerufen wurde. Als Modus stehen u.a. `times(n)`, `atLeast(n)`, `atMost(n)`
+und `never()` zur Verfügung.
## Argument Matcher
-Die Klasse `ArgumentMatchers` stellt eine Reihe statischer Methoden wie z.B.
-`String anyString()` und `List anyList()` zur Verfügung, die ein flexibles
-Simulieren von Objekten und Prüfen von Methodenaufrufen ermöglichen.
+Die Klasse `ArgumentMatchers` bietet statische Methoden wie `anyString()` oder
+`anyList()`, um beim Simulieren und Verifizieren flexible Eingabebedingungen
+festzulegen.
## Beispiel
diff --git a/docs/documentation/object.md b/docs/documentation/object.md
index a618897691..3eae6ce980 100644
--- a/docs/documentation/object.md
+++ b/docs/documentation/object.md
@@ -5,17 +5,17 @@ sidebar_position: 190
tags: [object]
---
-Alle Klassen in Java sind letztlich Unterklassen der Klasse `Object`. Daher wird
-diese auch als die Mutter aller Klassen bezeichnet. Die Klasse vererbt ihren
+Alle Klassen in Java sind letztlich Unterklassen der Klasse `Object`, die daher
+auch als die _Mutter aller Klassen_ bezeichnet wird. Sie vererbt ihren
Unterklassen unter anderem die Methoden `boolean equals(object: Object)`,
-`int hashCode()` und `String toString()`. Diese drei Methoden sollte jede
-Unterklasse sinnvoll überschreiben.
+`int hashCode()` und `String toString()`. Diese drei Methoden sollte jede eigene
+Klasse sinnvoll überschreiben.
## Die Methode _boolean equals(object: Object)_
-Die Methode `boolean equals(object: Object)` prüft zwei Objekte auf Gleichheit.
-Zwei Objekte gelten dabei in der Regel als gleich, wenn all ihre Attribute
-gleich sind.
+Die Methode `boolean equals(object: Object)` prüft zwei Objekte auf inhaltliche
+Gleichheit. Zwei Objekte gelten in der Regel als gleich, wenn alle ihre
+Attribute übereinstimmen.
```java title="Computer.java (Auszug)" showLineNumbers
public class Computer {
@@ -41,10 +41,10 @@ public class Computer {
## Die Methode _int hashCode()_
-Die Methode `int hashCode()` liefert den Hashcode des aktuellen Objektes zurück.
-Die Methode sollte so überschrieben werden, dass gleiche Objekte den gleichen
-Hashwert zurückgeben. Dies ist vor allem beim Arbeiten mit Hash-basierten
-Datensammlungen wie z.B. der Klasse `HashMap` notwendig.
+Die Methode `int hashCode()` liefert den Hashcode des aktuellen Objekts zurück.
+Sie sollte so überschrieben werden, dass inhaltlich gleiche Objekte denselben
+Hashwert liefern. Das ist insbesondere beim Arbeiten mit Hash-basierten
+Datensammlungen wie `HashMap` notwendig.
```java title="Computer.java (Auszug)" showLineNumbers
public class Computer {
@@ -60,19 +60,18 @@ public class Computer {
:::info
-Die statische Methode `int hash(values: Object...)` der Klasse `Objects` liefert
-eine einfache Möglichkeit zur Implementierung der Methode `boolean hashCode()`.
+Die statische Methode `int hash(values: Object...)` der Klasse `Objects` bietet
+eine einfache Möglichkeit zur Implementierung von `hashCode()`.
:::
## Die Methode _String toString()_
-Die Methode `String toString()` liefert eine eindeutige Kennung des Objektes in
-der Form _[Vollständiger Klassenname]_@_[Adresse des Objektes im Hauptspeicher
-in hexadezimaler Notation]_ zurück. Die Methode sollte so überschrieben werden,
-dass alle relevanten Attribute des Objektes als Zeichenkette zurückgegeben
-werden. In der Regel geschieht dies in der Form _[Klassenname]
-[[Attribut]=[Attributswert], ...]_.
+Die Methode `String toString()` liefert eine eindeutige Kennung des Objekts in
+der Form _[vollständiger Klassenname]_@_[Adresse im Hauptspeicher in
+hexadezimaler Notation]_ zurück. Üblicherweise wird sie so überschrieben, dass
+alle relevanten Attribute als Zeichenkette zurückgegeben werden — typischerweise
+in der Form _[Klassenname][Attribut]=[Wert], ...]_.
```java title="Computer.java" showLineNumbers
public class Computer {
diff --git a/docs/documentation/oo.md b/docs/documentation/oo.md
index 24c170b53b..88b15f2f7d 100644
--- a/docs/documentation/oo.md
+++ b/docs/documentation/oo.md
@@ -6,24 +6,22 @@ tags: [oo]
---
Die reale Welt besteht aus Objekten mit individuellen Eigenschaften und
-individuellem Verhalten. Für ein einfacheres Verständnis werden Objekte
-kategorisiert, also zu sinnhaften Einheiten verbunden. In der objektorientierten
-Programmierung werden Beobachtungen aus der realen Welt zum Konzept der
-Objektorientierung zusammengefasst:
+individuellem Verhalten. Um diese Komplexität handhabbar zu machen, werden
+Objekte kategorisiert und zu sinnvollen Einheiten zusammengefasst. Die
+objektorientierte Programmierung überträgt dieses Prinzip auf Software:
-- Eine Kategorie von ähnlichen Objekten bezeichnet man als _Klasse_
-- Konkrete Ausprägungen bzw. Instanzen einer Klasse werden wiederum als
- _Objekte_ bezeichnet
-- Die Eigenschaften von Objekten werden als _Attribute_ das Verhalten als
+- Eine Kategorie ähnlicher Objekte bezeichnet man als _Klasse_
+- Konkrete Ausprägungen einer Klasse nennt man _Objekte_ (auch _Instanzen_)
+- Die Eigenschaften von Objekten werden als _Attribute_, ihr Verhalten als
_Methoden_ bezeichnet
## Datenkapselung
Ein wesentlicher Grundsatz der Objektorientierung ist, dass Attribute durch
-Methoden gekapselt werden. Datenkapselung bedeutet, dass auf Attribute nicht
+Methoden gekapselt werden. _Datenkapselung_ bedeutet, dass auf Attribute nicht
direkt zugegriffen werden kann, sondern nur indirekt über Methoden. Typische
-Methoden zum Lesen und Schreiben von Attributen sind die sogenannten Getter bzw.
-Setter (auch Set- und Get-Methoden bzw. Accessors genannt).
+Methoden zum Lesen und Schreiben von Attributen sind Getter bzw. Setter (auch
+Accessors und Mutators genannt).
```mermaid
flowchart LR
@@ -44,13 +42,12 @@ flowchart LR
## Abstraktion
-Abstraktion bedeutet das Zerlegen von komplexen Systeme in kleinere,
-überschaubare Einheiten, indem der Fokus auf die wesentlichen Eigenschaften und
-das wesentliche Verhalten gesetzt und unwichtige Details ausgeblendet werden.
-Dies bringt einige Vorteile wie bessere Wiederverwendbarkeit, bessere
-Wartbarkeit sowie bessere Lesbarkeit mit sich. In der Objektorientierten
-Programmierung erfolgt die Abstraktion durch den Einsatz von (abstrakten)
-Klassen bzw. Schnittstellen (Interfaces).
+_Abstraktion_ bedeutet, komplexe Systeme in kleinere, überschaubare Einheiten zu
+zerlegen — indem der Fokus auf die wesentlichen Eigenschaften und das
+wesentliche Verhalten gelegt und unwichtige Details ausgeblendet werden. Das
+bringt Vorteile wie bessere Wiederverwendbarkeit, Wartbarkeit und Lesbarkeit. In
+Java wird Abstraktion durch den Einsatz von (abstrakten) Klassen und
+Schnittstellen (Interfaces) realisiert.
```mermaid
flowchart LR
diff --git a/docs/documentation/operators.mdx b/docs/documentation/operators.mdx
index aa614fdc88..5b05ba0a1f 100644
--- a/docs/documentation/operators.mdx
+++ b/docs/documentation/operators.mdx
@@ -9,17 +9,16 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Operatoren sind Zeichen, mit denen Daten manipuliert werden können. Mit Hilfe
-von Operanden und Operatoren können beliebig komplexe Ausdrücke abgebildet
-werden. Operatoren mit einem, zwei oder drei Operanden werden als _unäre
-Operatoren_ _binäre Operatoren_ und _ternäre Operatoren_ bezeichnet. Man
-unterscheidet zudem zwischen arithmetischen, bitweisen und logischen Operatoren
-sowie Vergleichsoperatoren.
+von Operanden und Operatoren lassen sich beliebig komplexe Ausdrücke aufbauen.
+Operatoren mit einem, zwei oder drei Operanden werden als _unäre_, _binäre_ bzw.
+_ternäre_ Operatoren bezeichnet. Man unterscheidet zwischen arithmetischen,
+bitweisen und logischen Operatoren sowie Vergleichsoperatoren.
-Für die arithmetischen Grundrechenarten stehen verschiedene arithmetische
-Operatoren zur Verfügung.
+Für die arithmetischen Grundrechenarten stehen folgende Operatoren zur
+Verfügung.
| Ausdruck mit Operator | Bedeutung |
| --------------------- | ------------------------------------------------------------- |
@@ -36,8 +35,8 @@ Operatoren zur Verfügung.
-Bitweise Operatoren können dazu verwendet werden, Binäroperationen auf Operanden
-durchzuführen.
+Bitweise Operatoren führen Operationen direkt auf den einzelnen Bits der
+Operanden durch.
| Ausdruck mit Operator | Bedeutung |
| --------------------- | ------------------------ |
@@ -49,8 +48,8 @@ durchzuführen.
-Logische Operatoren können dazu verwendet werden, logische Aussagen miteinander
-zu verknüpfen.
+Logische Operatoren verknüpfen logische Aussagen miteinander und liefern einen
+booleschen Wert zurück.
| Ausdruck mit Operator | Bedeutung |
| --------------------- | ------------------------ |
@@ -61,8 +60,8 @@ zu verknüpfen.
-Logische Bedingungen für zwei Werte eines elementaren Datentyps können durch
-Vergleichsoperatoren realisiert werden.
+Vergleichsoperatoren prüfen logische Bedingungen für zwei Werte eines
+elementaren Datentyps und liefern einen booleschen Wert zurück.
| Ausdruck mit Operator | Bedeutung |
| --------------------- | ---------------------- |
@@ -76,8 +75,8 @@ Vergleichsoperatoren realisiert werden.
:::info
Da der Vergleichsoperator `==` auf referenzielle Gleichheit prüft, sollte zum
-Vergleich von zwei Objekten die Methode `boolean equals(object: Object)`
-verwendet werden.
+inhaltlichen Vergleich von zwei Objekten die Methode
+`boolean equals(object: Object)` verwendet werden.
:::
@@ -86,7 +85,8 @@ verwendet werden.
## Priorität von Operatoren
-Die Verarbeitung von Operatoren erfolgt gemäß ihrer Priorität.
+Die Auswertung von Ausdrücken mit mehreren Operatoren erfolgt gemäß ihrer
+Priorität. Operatoren mit höherer Priorität werden zuerst ausgewertet.
| Priorität | Operator |
| --------- | ------------------------------------------------------------ |
diff --git a/docs/documentation/optionals.md b/docs/documentation/optionals.md
index cc209becf8..0fc42c520f 100644
--- a/docs/documentation/optionals.md
+++ b/docs/documentation/optionals.md
@@ -5,10 +5,9 @@ sidebar_position: 290
tags: [optionals]
---
-Der Umgang mit null-Werten stellt in vielen Programmiersprachen eine große
-Herausforderung dar. Zur Vermeidung von Laufzeitfehlern (`NullPointerException`)
-müsste vor jedem Methodenaufruf eigentlich überprüft werden, ob ein gültiger
-Wert vorliegt oder nicht.
+Der Umgang mit `null`-Werten ist in vielen Programmen eine häufige Fehlerquelle.
+Ohne explizite Prüfungen kann der Zugriff auf ein `null`-Objekt eine
+`NullPointerException` auslösen.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -18,7 +17,7 @@ public class MainClass {
public static void main(String[] args) {
names = new ArrayList<>();
String name = getNameByInitial('H');
- System.out.println(name.length()); // Laufzeitfehler
+ System.out.println(name.length()); // Laufzeitfehler: name ist null
}
public static String getNameByInitial(char initial) {
@@ -35,16 +34,14 @@ public class MainClass {
}
```
-Die Klasse `Optional` ermöglicht in Java eine komfortable Möglichkeit, mit
-null-Werten umzugehen. Das eigentliche Objekt wird dabei in einem Objekt der
-Klasse `Optional` verpackt; der Zugriff auf das verpackte Objekt erfolgt über
-entsprechende Methoden. Dies stellt sicher, dass sich der Entwickler mit
-null-Werten auseinander setzen muss.
+Die Klasse `Optional` bietet eine komfortable Möglichkeit, mit `null`-Werten
+umzugehen. Das eigentliche Objekt wird in einem `Optional`-Objekt verpackt; der
+Zugriff erfolgt über entsprechende Methoden. So wird sichergestellt, dass der
+`null`-Fall explizit behandelt werden muss.
-Für den Umgang mit null-Werten stellt die Klasse `Optional` Methoden wie
-`T get()`, `boolean isPresent()` und `void ifPresent(consumer: Consumer)` zur
-Verfügung. Zudem existieren Methoden wie `void orElse(other: T)`, mit denen
-Standardwerte festgelegt werden können.
+Die Klasse `Optional` stellt u.a. folgende Methoden bereit: `T get()`,
+`boolean isPresent()`, `void ifPresent(consumer: Consumer)` und
+`T orElse(other: T)` zum Festlegen eines Standardwerts.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/polymorphism.mdx b/docs/documentation/polymorphism.mdx
index 31bc17c23c..500fd2a7f6 100644
--- a/docs/documentation/polymorphism.mdx
+++ b/docs/documentation/polymorphism.mdx
@@ -8,17 +8,15 @@ tags: [oo, polymorphism]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Unter (dynamischer) Polymorphie (griechisch für Vielgestaltigkeit) versteht man,
-dass eine Referenzvariable zur Laufzeit durch Typumwandlung Referenzen auf
-Objekte unterschiedlicher Klassen besitzen kann und dass dadurch
-unterschiedliche Methodenimplementierungen aufgerufen werden können. Man spricht
-in diesem Zusammenhang auch vom _statischen Datentyp einer Referenzvariablen_
-(der zur Designzeit festgelegt wird) und vom _dynamischen Datentyp einer
-Referenzvariablen_ (der zur Laufzeit zugewiesen wird). Der statische Typ legt
-fest, welche Methoden aufgerufen werden können, der dynamische, welche
-Methodenimplementierung aufgerufen wird. Die Typumwandlung von der abgeleiteten
-Unterklasse zur Oberklasse bezeichnet man als _Upcast_, die Rückumwandlung als
-_Downcast_.
+Unter _(dynamischer) Polymorphie_ (griechisch für „Vielgestaltigkeit") versteht
+man, dass eine Referenzvariable zur Laufzeit Referenzen auf Objekte
+unterschiedlicher Klassen halten kann und dadurch unterschiedliche
+Methodenimplementierungen aufgerufen werden. Man unterscheidet dabei zwischen
+dem _statischen Datentyp_ (zur Designzeit festgelegt) und dem _dynamischen
+Datentyp_ (zur Laufzeit zugewiesen). Der statische Typ bestimmt, welche Methoden
+aufrufbar sind; der dynamische Typ bestimmt, welche Implementierung tatsächlich
+ausgeführt wird. Die Typumwandlung von der Unterklasse zur Oberklasse nennt man
+_Upcast_, die Rückumwandlung _Downcast_.
@@ -106,12 +104,10 @@ werden. Der Downcast einer nicht zuweisungskompatiblen Referenz führt zu einer
## Der instanceof-Operator
-Mit dem Operator `instanceof` kann zur Laufzeit geprüft werden, ob eine
-Objektreferenz zuweisungskompatibel zu einer Klasse ist. Eine Objektreferenz ist
-dann zuweisungskompatibel zu einer Klasse, wenn die Klasse des referenzierten
-Objektes in einer Vererbungsbeziehung zur Klasse steht. Seit Java 16 ermöglicht
-der Mustervergleich bei `instanceof` das Vermeiden notwendiger Typumwandlungen
-und sorgt gleichzeitig für eine sicherere Programmierung.
+Mit dem Operator `instanceof` lässt sich zur Laufzeit prüfen, ob eine
+Objektreferenz mit einer bestimmten Klasse zuweisungskompatibel ist. Seit Java
+16 ermöglicht der Mustervergleich (_Pattern Matching_) bei `instanceof` das
+direkte Binden in eine neue Variable ohne expliziten Downcast.
```java title="MainClass.java (Auszug)" showLineNumbers
public class MainClass {
@@ -119,13 +115,13 @@ public class MainClass {
public static void main(String[] args) {
...
for (Computer c : computers) {
- /* bis Java 16 */
+ // bis Java 16: expliziter Downcast erforderlich
if (c instanceof Notebook) {
- Notebook notebook = (Notebook) c; // Downcast
+ Notebook notebook = (Notebook) c;
System.out.println(notebook.getScreenSizeInInches());
}
- /* seit Java 16 */
- if (c instanceof Notebook notebook) { // Downcast
+ // seit Java 16: Pattern Matching
+ if (c instanceof Notebook notebook) {
System.out.println(notebook.getScreenSizeInInches());
}
}
diff --git a/docs/documentation/pseudo-random-numbers.md b/docs/documentation/pseudo-random-numbers.md
index 15037d9b39..ecc479cf89 100644
--- a/docs/documentation/pseudo-random-numbers.md
+++ b/docs/documentation/pseudo-random-numbers.md
@@ -5,9 +5,11 @@ sidebar_position: 80
tags: [java-api, random]
---
-Die Klasse `Random` ermöglicht das Erzeugen von Pseudozufallszahlen.
-Pseudozufallszahlen sind scheinbar zufällige Zahlen, die aber auf Grund einer
-Formel berechnet werden.
+Die Klasse `Random` aus dem Paket `java.util` ermöglicht das Erzeugen von
+Pseudozufallszahlen. Als _pseudozufällig_ bezeichnet man Zahlen, die zwar
+zufällig wirken, aber durch einen deterministischen Algorithmus auf Basis eines
+Startwerts (Seed) berechnet werden. Wird kein Seed angegeben, verwendet Java die
+aktuelle Systemzeit.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -16,6 +18,7 @@ public class MainClass {
Random random = new Random();
int randomNumber;
+ // 100 Zufallszahlen von 1 bis 100 ausgeben
for (int i = 0; i < 100; i++) {
randomNumber = random.nextInt(100) + 1;
System.out.println(randomNumber);
@@ -24,3 +27,19 @@ public class MainClass {
}
```
+
+Die folgende Tabelle zeigt häufig verwendete Methoden der Klasse `Random`.
+
+| Methode | Rückgabetyp | Beschreibung |
+| --------------------- | ----------- | --------------------------------------------------------------- |
+| `nextInt()` | `int` | Gibt eine zufällige `int`-Zahl zurück |
+| `nextInt(bound: int)` | `int` | Gibt eine zufällige `int`-Zahl im Bereich 0 bis bound−1 zurück |
+| `nextDouble()` | `double` | Gibt eine zufällige `double`-Zahl im Bereich 0.0 bis 1.0 zurück |
+| `nextBoolean()` | `boolean` | Gibt zufällig `true` oder `false` zurück |
+
+:::info
+
+Mit `random.nextInt(n) + 1` lassen sich gleichverteilte Zufallszahlen im Bereich
+1 bis n erzeugen.
+
+:::
diff --git a/docs/documentation/records.md b/docs/documentation/records.md
index 80421e4fd0..ca8d9da484 100644
--- a/docs/documentation/records.md
+++ b/docs/documentation/records.md
@@ -5,10 +5,10 @@ sidebar_position: 250
tags: [records]
---
-Datenklassen sind Klassen die lediglich der Kapselung unveränderlicher Daten
-dienen. Daher bestehen Datenklassen häufig aus Boilerplate-Code. Unter
-Boilerplate-Code versteht man Anweisungblöcke, die an verschiedenen Stellen mehr
-oder weniger identisch verwendet werden.
+Datenklassen sind Klassen, die ausschließlich der Kapselung unveränderlicher
+Daten dienen. Sie bestehen häufig aus viel _Boilerplate-Code_ — also
+Codeabschnitten, die an verschiedenen Stellen nahezu identisch wiederkehren
+(Konstruktor, Getter, `equals`, `hashCode`, `toString`).
```java title="Student.java" showLineNumbers
public final class Student {
@@ -57,11 +57,10 @@ public final class Student {
}
```
-Seit Java 16 bieten Records die Möglichkeiten, Datenklassen einfach umzusetzen.
-Records sind spezielle Klassen, die anhand der festgelegten Parameter
-entsprechende Konstruktoren, Getter sowie Implementierungen für die Methoden
-`boolean equals(object: Object)`, `int hashCode()` und `String toString()`
-erzeugen. Das Schlüsselwort für Records lautet `record`.
+Seit Java 16 bieten _Records_ eine kompakte Möglichkeit, Datenklassen zu
+definieren. Ein Record erzeugt anhand der deklarierten Parameter automatisch
+einen Konstruktor, Getter sowie Implementierungen für `equals`, `hashCode` und
+`toString`. Das Schlüsselwort dafür lautet `record`.
```java title="Student.java" showLineNumbers
public record Student(int id, String name) {}
diff --git a/docs/documentation/references-and-objects.mdx b/docs/documentation/references-and-objects.mdx
index a5c5f573e9..d7adcb56a8 100644
--- a/docs/documentation/references-and-objects.mdx
+++ b/docs/documentation/references-and-objects.mdx
@@ -8,14 +8,13 @@ tags: [oo]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-Technisch gesehen handelt es sich bei einer Klasse um einen komplexen Datentyp.
-Analog zu den primitiven Datentypen können auch für Klassen Variablen –
-sogenannte _Referenzvariablen_ – definiert werden.
+Technisch gesehen ist eine Klasse ein komplexer Datentyp. Analog zu primitiven
+Datentypen können für Klassen Variablen — sogenannte _Referenzvariablen_ —
+deklariert werden.
-Im Gegensatz zu "normalen" Variablen werden bei Referenzvariablen nicht die
-eigentlichen Werte in den Variablen gespeichert, sondern die Speicheradressen
-der erzeugten Objekte. Die Selbstreferenz `this` verweist innerhalb einer Klasse
-auf das eigene Objekt.
+Im Gegensatz zu einfachen Variablen speichern Referenzvariablen nicht den Wert
+direkt, sondern die Speicheradresse des erzeugten Objekts. Die Selbstreferenz
+`this` verweist innerhalb einer Klasse auf das eigene Objekt.
```mermaid
flowchart LR
@@ -45,14 +44,15 @@ flowchart LR
:::info
-Der Standarwert von Referenzvariablen ist `null` (auch Nullreferenz genannt).
+Der Standardwert von Referenzvariablen ist `null` (auch _Nullreferenz_ genannt).
:::
## Erzeugen von Objekten
-Beim Erzeugen eines Objekts mit Hilfe des Operators `new` wird der bei der
-Deklaration reservierte Speicherplatz durch das Objekt belegt.
+Mit dem `new`-Operator wird ein neues Objekt erzeugt und der zugehörige
+Speicherplatz belegt. Nach `new` muss immer ein
+[Konstruktor](classes#definition-von-konstruktoren) der Klasse angegeben werden.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -65,20 +65,11 @@ public class MainClass {
}
```
-:::info
-
-Nach dem new-Operator muss immer ein
-[Konstruktor](classes#definition-von-konstruktoren) der Klasse stehen.
-
-:::
-
## Zugriff auf Attribute und Aufruf von Methoden
-Erlauben die Zugriffsrechte den Zugriff auf ein Attribut bzw. den Aufruf einer
-Methode, kann über die deklarierte Referenzvariable und einem nachgestellten
-Punkt auf das Attribut zugegriffen bzw. die Methode aufgerufen werden. Der
-Zugriff auf statische Attribute bzw. der Aufruf statischer Methoden erfolgt über
-den Klassennamen sowie einem nachgestellten Punkt.
+Sofern die Zugriffsrechte es erlauben, erfolgt der Zugriff auf ein Attribut oder
+der Aufruf einer Methode über die Referenzvariable gefolgt von einem Punkt.
+Statische Attribute und Methoden werden über den Klassennamen angesprochen.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -88,7 +79,7 @@ public class MainClass {
Computer computer = new Computer("Mein Office PC");
computer.setCpu(cpu);
computer.setMemoryInGb(32);
- System.out.println(Computer.getNumberOfComputers());
+ System.out.println(Computer.getNumberOfComputers());
}
}
@@ -97,7 +88,6 @@ public class MainClass {
:::info
Beim Aufruf einer Methode müssen alle Parameter in der richtigen Reihenfolge
-versorgt werden. Parameter, die diesem Prinzip folgen, bezeichnet man als
-_Positionsparameter_
+übergeben werden. Solche Parameter bezeichnet man als _Positionsparameter_.
:::
diff --git a/docs/documentation/slf4j.mdx b/docs/documentation/slf4j.mdx
index 7d82e3b721..fd6dbd79b4 100644
--- a/docs/documentation/slf4j.mdx
+++ b/docs/documentation/slf4j.mdx
@@ -8,19 +8,18 @@ tags: [slf4j]
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-[Simple Logging Facade for Java (SLF4J)](https://www.slf4j.org/) stellt eine
-externe Java-Bibliothek dar, die das Protokollieren in Java-Anwendungen
-ermöglicht. Protokollierung (Logging) ist ein wesentlicher Bestandteil der
-Softwareentwicklung und -wartung und bietet zahlreiche Vorteile wie
-Fehlerbehebung, Überwachung, Audit, Compliance, Debugging, Leistungsanalyse
-sowie Benutzerunterstützung. Durch die effektive Nutzung von Protokollierung
-kann die Zuverlässigkeit, Sicherheit und Leistung einer Anwendung erheblich
-verbessert werden.
+[Simple Logging Facade for Java (SLF4J)](https://www.slf4j.org/) ist eine
+externe Java-Bibliothek für strukturiertes Logging. Logging ist ein zentraler
+Bestandteil professioneller Softwareentwicklung und unterstützt bei
+Fehlerbehebung, Überwachung, Debugging und Leistungsanalyse. SLF4J ist eine
+Abstraktionsschicht (Fassade) und benötigt eine konkrete
+Logging-Implementierung, z.B.
+[Log4J](https://logging.apache.org/log4j/2.x/index.html).
## Protokollierungs-Level
-SLF4J definiert verschiedene Protokollierungs-Level, die die Schwere oder
-Wichtigkeit der zu protokollierenden Nachrichten angeben.
+SLF4J definiert fünf Protokollierungs-Level, die die Schwere oder Wichtigkeit
+einer Nachricht angeben.
| Level | Beschreibung |
| ----- | ------------------------------------------------------------------------------------------------------------------------ |
@@ -32,18 +31,15 @@ Wichtigkeit der zu protokollierenden Nachrichten angeben.
## Protokollierungs-Implementierungen
-Die Art der Speicherung von Protokollen in einer Anwendung, die SLF4J verwendet,
-hängt von der konkreten Implementierung ab. SLF4J selbst ist dabei nur eine
-Fassade und benötigt eine konkrete Implementierung, um die tatsächliche
-Protokollierung durchzuführen. Eine der am weitesten verbreiteten
-Protokollierungs-Bibliotheken für Java ist
-[Log4J](https://logging.apache.org/log4j/2.x/index.html), welches die Ausgabe
-von Protokollen auf der Konsole sowie in Protokoll-Dateien ermöglicht.
+SLF4J selbst ist nur eine Fassade und führt keine Protokollierung durch. Für die
+tatsächliche Ausgabe ist eine konkrete Implementierung nötig. Eine der
+gebräuchlichsten ist Log4J, das Protokolle sowohl auf der Konsole als auch in
+Dateien ausgeben kann.
## Beispiel
-Für die Klasse `MainClass` wird ein Logger initialisiert, mit dessen Hilfe
-verschiedene Nachrichten in der Datei _logs/app.log_ protokolliert werden.
+Die Klasse `Names` liest Namen aus einer Datei. Ein Logger protokolliert dabei
+die wichtigsten Schritte und schreibt die Ausgaben in die Datei _logs/app.log_.
diff --git a/docs/documentation/strings.md b/docs/documentation/strings.md
index 6a275178e3..683e55f4df 100644
--- a/docs/documentation/strings.md
+++ b/docs/documentation/strings.md
@@ -5,10 +5,11 @@ sidebar_position: 50
tags: [java-api, strings]
---
-Ketten von beliebigen Zeichen werden durch die Klasse `String` realisiert. Diese
-stellt einige hilfreiche Methoden zur Verfügung, die bei der Analyse und der
-Verarbeitung von Zeichenketten Verwendung finden. Die Angabe einer Zeichenkette
-erfolgt über die Anführungszeichen.
+Zeichenketten (Strings) sind Folgen beliebiger Zeichen und werden in Java durch
+die Klasse `String` realisiert. Sie ist keine primitive, sondern eine
+strukturierte Datentyp-Klasse und stellt zahlreiche Methoden zur Analyse und
+Verarbeitung von Zeichenketten bereit. Zeichenketten werden in Anführungszeichen
+geschrieben.
```java title="MainClass.java" showLineNumbers
public class MainClass {
@@ -17,34 +18,56 @@ public class MainClass {
String text = "Winter";
String text2 = "Coming";
+ // Zeichenketten verbinden
String text3 = text + " is " + text2;
- int length = text3.length();
- char charAt1 = text3.charAt(0);
- String upperCase = text3.toUpperCase();
+ int length = text3.length(); // Länge der Zeichenkette
+ char charAt1 = text3.charAt(0); // Zeichen an Position 0
+ String upperCase = text3.toUpperCase(); // In Großbuchstaben umwandeln
}
}
```
+Die folgende Tabelle zeigt häufig verwendete Methoden der Klasse `String`.
+
+| Methode | Rückgabetyp | Beschreibung |
+| ----------------------------------- | ----------- | ----------------------------------------------------------- |
+| `length()` | `int` | Gibt die Anzahl der Zeichen zurück |
+| `charAt(index: int)` | `char` | Gibt das Zeichen an der angegebenen Position zurück |
+| `indexOf(str: String)` | `int` | Gibt die erste Fundstelle der Teilzeichenkette zurück |
+| `substring(begin: int)` | `String` | Gibt den Teilstring ab der angegebenen Position zurück |
+| `substring(begin: int, end: int)` | `String` | Gibt den Teilstring zwischen begin und end zurück |
+| `toUpperCase()` | `String` | Wandelt alle Zeichen in Großbuchstaben um |
+| `toLowerCase()` | `String` | Wandelt alle Zeichen in Kleinbuchstaben um |
+| `trim()` | `String` | Entfernt führende und abschließende Leerzeichen |
+| `replace(old: String, new: String)` | `String` | Ersetzt alle Vorkommen eines Teilstrings durch einen neuen |
+| `contains(str: String)` | `boolean` | Prüft, ob die Zeichenkette einen Teilstring enthält |
+| `startsWith(prefix: String)` | `boolean` | Prüft, ob die Zeichenkette mit dem Präfix beginnt |
+| `endsWith(suffix: String)` | `boolean` | Prüft, ob die Zeichenkette mit dem Suffix endet |
+| `equals(other: Object)` | `boolean` | Prüft auf inhaltliche Gleichheit |
+| `equalsIgnoreCase(other: String)` | `boolean` | Prüft auf inhaltliche Gleichheit ohne Groß-/Kleinschreibung |
+| `split(regex: String)` | `String[]` | Teilt die Zeichenkette anhand eines Trennzeichens auf |
+
## Escape-Sequenzen
Steuer- und Sonderzeichen in Zeichenketten können mit Hilfe einer Escape-Sequenz
-realisiert werden.
+eingefügt werden.
-| Escape-Squenz | Beschreibung |
-| ------------------- | ----------------- |
-| \\n | Zeilensprung |
-| \\t | Tabulatorsprung |
-| \\\\ | Schräger rechts |
-| \\" | Anführungszeichen |
-| \\' | Hochkomma |
-| \\u0000 bis \\uFFFF | Unicode-Zeichen |
+| Escape-Sequenz | Beschreibung |
+| --------------------- | ----------------- |
+| `\n` | Zeilenumbruch |
+| `\t` | Tabulatorzeichen |
+| `\\` | Backslash |
+| `\"` | Anführungszeichen |
+| `\'` | Hochkomma |
+| `\u0000` bis `\uFFFF` | Unicode-Zeichen |
## Textblöcke
Seit Java 15 ermöglichen Textblöcke mehrzeilige Zeichenketten ohne umständliche
-Umwege.
+Escape-Sequenzen. Der Inhalt wird durch drei Anführungszeichen (`"""`)
+eingeschlossen.
```java title="MainClass.java" showLineNumbers
public class MainClass {
diff --git a/docs/documentation/tests.md b/docs/documentation/tests.md
index 9bd8be8552..59f95eceaa 100644
--- a/docs/documentation/tests.md
+++ b/docs/documentation/tests.md
@@ -5,11 +5,10 @@ sidebar_position: 310
tags: [tests]
---
-Softwaretests sollen sicherstellen, dass bei der Entwicklung oder Änderung einer
-Software der Quellcode in allen festgelegten Anwendungsfällen korrekt
-funktioniert. Mit Hilfe von Softwaretests können Softwareentwickler im Idealfall
-schon während des Entwicklungsprozesses mögliche Fehler identifizieren und
-beheben. Man unterscheidet dabei zwischen verschiedenen Testarten:
+Softwaretests stellen sicher, dass eine Anwendung in allen vorgesehenen
+Anwendungsfällen korrekt funktioniert. Durch frühzeitiges Testen können Fehler
+bereits während der Entwicklung erkannt und behoben werden. Man unterscheidet
+vier Testebenen:
- Akzeptanztests: Testen des gesamten Systems unter realitätsgetreuen
Bedingungen
@@ -17,15 +16,13 @@ beheben. Man unterscheidet dabei zwischen verschiedenen Testarten:
- Integrationstests: Testen mehrerer, voneinander abhängiger Komponenten
- Komponententests: Testen einzelner, abgeschlossener Softwarebausteine
-Komponententests (Unit Tests) sowie Integrationstests spielen vor allem bei
-agilen Vorgehensweisen wie z.B. der testgetriebenen Entwicklung (Test Driven
-Development) eine große Rolle. Hierbei werden Anwendungen Schritt für Schritt
-(also inkrementell) um neue Funktionen erweitert (z.B. nach der
-Red-Green-Refactor-Methode): Zuerst wird ein Test geschrieben, der zunächst
-fehlschlägt (Red), anschließend wird genau soviel Produktivcode geschrieben,
-damit der Test erfolgreich durchläuft (Green). Schließlich werden beim
-Refactoring Testcode und Produktivcode aufgeräumt (also vereinfacht und
-verbessert).
+Komponententests (Unit Tests) sowie Integrationstests spielen besonders bei
+agilen Vorgehensweisen wie der testgetriebenen Entwicklung (Test Driven
+Development) eine wichtige Rolle. Beim TDD wird eine Anwendung inkrementell nach
+der Red-Green-Refactor-Methode entwickelt: Zunächst wird ein Test geschrieben,
+der fehlschlägt (Red). Dann wird gerade so viel Produktivcode geschrieben, dass
+der Test besteht (Green). Anschließend wird der Code aufgeräumt und vereinfacht
+(Refactor).
```mermaid
flowchart LR
diff --git a/docs/documentation/trees.md b/docs/documentation/trees.md
index a23b17f243..9100396a69 100644
--- a/docs/documentation/trees.md
+++ b/docs/documentation/trees.md
@@ -5,14 +5,12 @@ sidebar_position: 347
tags: [trees]
---
-Bäume sind abstrakte Datenstrukturen zum Darstellen von hierarchischen
-Strukturen. Sie bestehen i.d.R. aus beliebig vielen Elementen (Knoten), sowie
-Verbindungen zwischen den Elementen (Kanten). Den Ursprungsknoten bezeichnet man
-als _Wurzelknoten_, untergeordnete Knoten als _Kindknoten_, übergeordnete Knoten
-als _Elternknoten_ und Kinder ohne weitere untergeordnete Knoten als
-_Blattknoten_. Bäume sind im Prinzip Erweiterungen von Listen: in einer Liste
-hat ein Knoten maximal einen Nachfolger, in einem Baum kann ein Knoten mehrere
-Nachfolger besitzen.
+Bäume sind abstrakte Datenstrukturen zur Darstellung hierarchischer Beziehungen.
+Sie bestehen aus Knoten und Kanten zwischen den Knoten. Der oberste Knoten heißt
+_Wurzelknoten_, Knoten ohne Kindknoten heißen _Blattknoten_, dazwischenliegende
+Knoten sind gleichzeitig _Kind-_ und _Elternknoten_. Bäume erweitern das Konzept
+der Liste: Während ein Listenknoten maximal einen Nachfolger hat, kann ein
+Baumknoten mehrere Nachfolger besitzen.
```mermaid
flowchart
@@ -43,10 +41,9 @@ Knoten und unter dem Grad eines Knotens die Anzahl seiner Kindknoten.
## Binärbäume
-Bei Binärbäumen darf jeder Knoten maximal zwei Nachfolger besitzen. Besitzen
-alle inneren Knoten eines Binärbaumes den Grad 2, spricht man von einem _vollen
-Binärbaum_, besitzen alle Blätter eines vollen Binärbaum die gleiche Tiefe,
-spricht man von einem _vollständigen Binärbaum_.
+Bei Binärbäumen hat jeder Knoten maximal zwei Nachfolger. Hat jeder innere
+Knoten genau zwei Kinder, spricht man von einem _vollen Binärbaum_. Haben dabei
+alle Blattknoten dieselbe Tiefe, heißt er _vollständiger Binärbaum_.
```mermaid
flowchart TD
@@ -89,15 +86,14 @@ flowchart TD
## Traversierung von Bäumen
-Unter der Traversierung eines Baumes versteht man das Durchlaufen aller Elemente
-eines Baumes. Im Gegensatz zu Listen, wo es genau eine natürliche Ordnung für
-den Durchlauf der Elemente gibt (von vorne nach hinten), existieren bei Bäumen
-mehrere sinnvolle Reihenfolgen:
+Unter Traversierung versteht man das systematische Durchlaufen aller Knoten
+eines Baumes. Anders als bei Listen, wo die Reihenfolge eindeutig ist, gibt es
+bei Bäumen mehrere sinnvolle Durchlaufreihenfolgen:
-- Beim Tiefendurchlauf wird ausgehend vom Wurzelknoten zunächst der linke
- Teilbaum mit Tiefendurchlauf besucht, anschließend der rechte Teilbaum
-- Beim Breitendurchlauf werden die Knoten nach der Breite des Baumes geordnet
- besucht
+- Beim Tiefendurchlauf wird ausgehend vom Wurzelknoten zuerst der linke, dann
+ der rechte Teilbaum rekursiv besucht.
+- Beim Breitendurchlauf werden alle Knoten ebenenweise von oben nach unten
+ besucht.
```mermaid
flowchart TD
diff --git a/docs/documentation/unit-tests.md b/docs/documentation/unit-tests.md
index 78d3b6af4d..4ec616ca77 100644
--- a/docs/documentation/unit-tests.md
+++ b/docs/documentation/unit-tests.md
@@ -5,23 +5,17 @@ sidebar_position: 320
tags: [unit-tests]
---
-Komponententests (Unit Tests) werden zum Testen einzelner, abgeschlossener
-Softwarebausteine verwendet. JUnit ist ein weit verbreitetes Framework zur
-Erstellung dieser Komponententests bzw. zum automatisierten Testen von Klassen
-und Methoden in Java. Die aktuelle Version _JUnit 5_ stellt eine Kombination
-verschiedener Module der Projekte _JUnit Platform_, _JUnit Jupiter_ sowie _JUnit
-Vintage_ dar. Unter einem Framework versteht man ein Programmiergerüst, welches
-die Architektur für die Anwendung vorgibt und den Kontrollfluss der Anwendung
-steuert. Die Arbeitsweise von Frameworks wird als _Inversion of Control_
-bezeichnet: Die Funktionen einer Anwendung werden beim Framework registriert,
-welches die Funktionen zu einem späteren Zeitpunkt aufruft, d.h. die Steuerung
-des Kontrollfluss obliegt nicht der Anwendung, sondern dem Framework. Die Umkehr
-der Steuerung kann auch als Anwendung des Hollywood-Prinzips (_Don´t call us,
-we´ll call you_) verstanden werden.
+Komponententests (Unit Tests) testen einzelne, abgeschlossene Softwarebausteine
+isoliert. JUnit ist das am weitesten verbreitete Framework für Unit Tests in
+Java. Die aktuelle Version _JUnit 5_ setzt sich aus den Modulen _JUnit
+Platform_, _JUnit Jupiter_ und _JUnit Vintage_ zusammen. Als Framework gibt
+JUnit die Architektur und den Kontrollfluss der Tests vor (_Inversion of
+Control_): Die Testmethoden werden beim Framework registriert, und JUnit ruft
+sie auf — nach dem Hollywood-Prinzip: _Don't call us, we'll call you_.
## Implementieren einer Testklasse
-JUnit-Testklassen werden mit Hilfe entsprechender Annotationen implementiert:
+JUnit-Testklassen werden durch spezielle Annotationen gesteuert:
- Die Annotationen `@Test` und `@ParameterizedTest` definieren einfache bzw.
parametrisierte Testmethoden
@@ -37,10 +31,10 @@ JUnit-Testklassen werden mit Hilfe entsprechender Annotationen implementiert:
## Zusicherungen (Assertions)
-Die Klasse `Assertions` stellt verschiedene Methoden bereit, die immer dann eine
-Ausnahme vom Typ `AssertionError` auslösen, wenn das Ergebnis eines
-Methodenaufrufs nicht wie erwartet ausgefallen ist. Eine Ausnahme vom Typ
-`AssertionError` führt dazu, dass der Test als nicht erfolgreich gewertet wird.
+Die Klasse `Assertions` stellt Methoden bereit, die einen `AssertionError`
+auslösen, wenn das tatsächliche Ergebnis nicht dem erwarteten Ergebnis
+entspricht. Schlägt eine Zusicherung fehl, wird der Test als nicht erfolgreich
+gewertet.
| Assert-Methode | Bedeutung |
| ---------------------------------------------------------------- | ------------------------------------------- |
@@ -56,8 +50,8 @@ Methodenaufrufs nicht wie erwartet ausgefallen ist. Eine Ausnahme vom Typ
## Beispiel
-Die Klasse `Calculator` stellt mehrere Methoden bereit, die getestet werden
-sollen.
+Die Klasse `Calculator` stellt einfache mathematische Operationen bereit, die
+mit JUnit getestet werden sollen.
```java title="Calculator.java" showLineNumbers
public class Calculator {
@@ -79,10 +73,10 @@ public class Calculator {
}
```
-Die statische Methode `setUp()` der Testklasse `CalculatorTest` stellt sicher,
-dass vor der Ausführung der Testmethoden ein Taschenrechner-Objekt erzeugt wird.
-In den Testmethoden werden verschiedene Testfälle wie z.B. die Division durch
-Null getestet.
+Die Methode `setUp()` der Testklasse `CalculatorTest` initialisiert das
+Taschenrechner-Objekt vor allen Tests. Die Testmethoden decken verschiedene
+Szenarien ab, darunter die Multiplikation mit null, Absolutwerte und die
+Division durch null.
```java title="MainClass.java" showLineNumbers
public class CalculatorTest {
@@ -119,10 +113,9 @@ public class CalculatorTest {
:::info
-Für die Benennungen von Testmethoden wird in der Regel versucht, die
-wesentlichen Informationen eines Tests (Name der zu testenden Methode,
-vorgegebener Zustand, zu erwartendes Verhalten) in den Methodennamen zu
-integrieren. Zusätzlich können Schlüsselwörter wie _Should_, _When_, oder _Then_
-verwendet werden.
+Für die Benennung von Testmethoden hat sich das Muster
+`methodName_zustand_erwartung` bewährt (z.B.
+`divide_byZero_ArithmeticException`). Zusätzlich können Schlüsselwörter wie
+_should_, _when_ oder _then_ eingesetzt werden.
:::
diff --git a/docs/documentation/wrappers.md b/docs/documentation/wrappers.md
index 819303807a..2b6738684f 100644
--- a/docs/documentation/wrappers.md
+++ b/docs/documentation/wrappers.md
@@ -5,30 +5,29 @@ sidebar_position: 141
tags: [java-api, wrappers]
---
-Wrapper-Klassen (auch Hüllenklassen genannt) verpacken primitive Datentypen in
-vollwertigen Klassen und erweitern so die primitiven Datentypen um hilfreiche
-Methoden. Das Verpacken eines primitiven Datentyps bezeichnet man als _Boxing_,
-das Entpacken als _Unboxing_.
+Wrapper-Klassen (auch _Hüllenklassen_ genannt) verpacken primitive Datentypen in
+vollwertige Objekte und erweitern sie so um nützliche Methoden. Das Verpacken
+eines primitiven Werts nennt man _Boxing_, das Entpacken _Unboxing_. Java führt
+diese Konvertierung in vielen Kontexten automatisch durch (_Autoboxing_).
```java title="MainClass.java" showLineNumbers
public class MainClass {
public static void main(String[] args) {
- Integer i = Integer.valueOf("631");
+ Integer i = Integer.valueOf("631"); // String in Integer umwandeln
System.out.println(i);
- Boolean b = Boolean.logicalXor(true, false);
+ Boolean b = Boolean.logicalXor(true, false); // logisches XOR
System.out.println(b);
- Character c = Character.toUpperCase('a');
+ Character c = Character.toUpperCase('a'); // Zeichen in Großbuchstaben
System.out.println(c);
}
}
```
-:::info
+:::note
-Wrapper-Klassen basieren auf dem Entwurfsmuster _Adapter_, welches die
-Kommunikation zwischen Klassen mit zueinander inkompatiblen Schnittstellen
-ermöglicht.
+Wrapper-Klassen basieren auf dem Entwurfsmuster _Adapter_, das die Kommunikation
+zwischen Klassen mit inkompatiblen Schnittstellen ermöglicht.
:::