- 1 Section
- 10 Lessons
- unbegrenzt
- Java Fortgeschritten10
- 1.1OOP in Java: Klassen, Kapselung, Konstruktoren
- 1.2Vererbung in Java
- 1.3Polymorphismus und Methodenüberschreibung
- 1.4Interfaces und abstrakte Klassen
- 1.5Collections: ArrayList, HashMap, LinkedList
- 1.6Generics und Typsicherheit
- 1.7Streams und Lambda-Ausdrücke
- 1.8Dateioperationen: IO und NIO
- 1.9Unit-Tests in Java: JUnit 5
- 1.10Praxisprojekt: Anwendung mit OOP und Tests
OOP in Java: Klassen, Kapselung, Konstruktoren
In K40a hast du die Java-Grundlagen kennengelernt – Variablen, Schleifen, Methoden. Das reicht für kleine Programme aus, stößt aber schnell an Grenzen, sobald du echte Anwendungen baust. Spätestens dann brauchst du objektorientierte Programmierung (OOP): das Prinzip, Code in Klassen zu strukturieren, die Daten und Verhalten zusammen kapseln.
K40b führt dich in die OOP-Welt von Java ein. Diese erste Lektion erklärt die Klassen-Grundlagen: was eine Klasse ist, was ein Objekt ist, wie Konstruktoren funktionieren, was Kapselung (Encapsulation) bedeutet und warum private und Getter/Setter so wichtig sind. Die nächsten Lektionen bauen darauf auf – Vererbung in L2, Polymorphismus in L3.
1) Klasse vs. Objekt
Eine Klasse ist ein Bauplan, ein Objekt ist eine konkrete Ausprägung dieses Bauplans. Klassisches Bild:
- Klasse
Auto: beschreibt, dass ein Auto Eigenschaften hat (Marke, Farbe, Tachostand) und Dinge tun kann (beschleunigen, bremsen) - Objekt: ein konkretes Auto – „mein blauer BMW mit 25.000 km" – ist ein einzelnes Exemplar
Aus einem Bauplan lassen sich beliebig viele Objekte erzeugen. Jedes Objekt hat seinen eigenen Zustand (eigene Werte für Marke, Farbe usw.), aber alle teilen sich denselben Code (dieselben Methoden).
2) Die einfachste Klasse
So sieht eine minimale Klasse in Java aus:
public class Auto { String marke; String farbe; int tachostand; }
Das ist alles. Auto ist eine Klasse mit drei Feldern (englisch fields, manchmal auch Attributen oder Eigenschaften). Sie hat noch keine Methoden, aber das ist bereits eine gültige Klasse.
Ein Objekt erzeugen und nutzen:
Auto meinAuto = new Auto(); meinAuto.marke = "BMW"; meinAuto.farbe = "blau"; meinAuto.tachostand = 25000; System.out.println(meinAuto.marke); // BMW
Das Schlüsselwort new ruft den Konstruktor auf und reserviert Speicher für das neue Objekt. meinAuto ist eine Referenz darauf.
3) UML-Notation einer Klasse
In der IT wird eine Klasse oft als kleines Kasten-Diagramm dargestellt (UML – Unified Modeling Language). Drei Bereiche: Name oben, Felder in der Mitte, Methoden unten:
private, + für publicSolche Diagramme begegnen dir in jeder Software-Dokumentation. In der IHK-Prüfung musst du sie lesen und manchmal selbst zeichnen können. Mehr zu OOP-Konzepten allgemein in K48 – OOP.
4) Konstruktoren
Ein Konstruktor ist eine spezielle Methode, die beim Erzeugen eines Objekts aufgerufen wird. Er hat denselben Namen wie die Klasse und keinen Rückgabetyp:
public class Auto { String marke; String farbe; int tachostand; // Konstruktor public Auto(String marke, String farbe) { this.marke = marke; this.farbe = farbe; this.tachostand = 0; // neues Auto: Tacho auf 0 } }
Damit lassen sich Objekte in einem Schritt initialisieren:
Auto a1 = new Auto("BMW", "blau"); Auto a2 = new Auto("VW", "rot");
Das Schlüsselwort this verweist auf das aktuelle Objekt. Wenn ein Parameter denselben Namen hat wie ein Feld, hilft this.feld, die beiden auseinanderzuhalten.
5) Standard-Konstruktor
Eine wichtige Java-Eigenheit: wenn du keinen Konstruktor definierst, erzeugt der Compiler automatisch einen Standard-Konstruktor ohne Parameter. Definierst du aber einen mit Parametern, ist der Standard-Konstruktor weg – außer du deklarierst ihn explizit:
public class Auto { String marke; public Auto() { } // ohne Parameter, falls gebraucht public Auto(String marke) { this.marke = marke; } } Auto a = new Auto(); // nutzt den ohne Parameter Auto b = new Auto("BMW"); // nutzt den mit Parameter
Mehrere Konstruktoren in einer Klasse zu haben heißt Konstruktor-Überladung. Sie müssen sich in Anzahl oder Typen der Parameter unterscheiden.
6) Methoden
Methoden sind Funktionen, die zu einer Klasse gehören. Sie können auf die Felder ihrer Klasse zugreifen:
public class Auto { String marke; int tachostand; public void beschleunigen(int kilometer) { tachostand += kilometer; } public int getTachostand() { return tachostand; } }
Aufruf:
Auto a = new Auto("BMW", "blau"); a.beschleunigen(100); a.beschleunigen(50); System.out.println(a.getTachostand()); // 150
7) Kapselung (Encapsulation)
Bisher konnten wir a.marke = "BMW" direkt schreiben – das Feld war von außen zugänglich. Das ist gefährlich: jeder kann beliebige Werte setzen, auch unsinnige (negativer Tachostand). Das Prinzip der Kapselung sagt: Felder werden versteckt, Zugriff nur über kontrollierte Methoden.
In Java setzt man dafür den Modifier private:
public class Auto { private String marke; private int tachostand; public Auto(String marke) { this.marke = marke; this.tachostand = 0; } // Getter public String getMarke() { return marke; } public int getTachostand() { return tachostand; } // Setter mit Validierung public void setTachostand(int wert) { if (wert < tachostand) { throw new IllegalArgumentException("Tacho kann nicht zurückgesetzt werden"); } tachostand = wert; } }
Ergebnis: niemand kann mehr a.tachostand = -100 machen. Wer den Tachostand setzen will, muss durch setTachostand(...) – und dort prüfen wir, dass der neue Wert nicht kleiner als der alte ist.
8) Kapselung visualisiert
Stell dir die Klasse wie ein Haus mit Mauer drumherum vor. Innen liegen die Felder, geschützt. Nach außen gibt's nur kontrollierte Türen (Methoden):
− private int tachostand
getTachostand() → tacho
throws bei ungültig
private): die rohen Daten, vor unkontrolliertem Zugriff geschützt. Außen (public): die Türen – Methoden, die den Zugriff regeln, validieren und protokollieren können. Klassenbenutzer brauchen nicht zu wissen, wie es drinnen aussieht.9) Die vier Sichtbarkeits-Modifier
Java kennt vier Zugriffsstufen. Sie regeln, von wo auf ein Feld oder eine Methode zugegriffen werden darf:
Faustregel: so restriktiv wie möglich. Felder fast immer private, Methoden meist public wenn sie zur Schnittstelle gehören, sonst private. protected brauchst du vor allem bei Vererbung.
10) Getter und Setter
Getter und Setter folgen in Java einer strengen Namenskonvention (JavaBeans-Konvention):
- Für ein Feld
name→getName()undsetName(String) - Für ein
boolean-Feldaktiv→isAktiv()stattgetAktiv() - Setter haben Rückgabetyp
voidund einen Parameter - Getter haben keinen Parameter und den passenden Rückgabetyp
Diese Konvention ist nicht nur Stil – viele Frameworks (Spring, JSP, Jackson für JSON, JPA für Datenbankzugriff) verlassen sich darauf. Halte dich daran, dann funktioniert dein Code automatisch mit dem Java-Ökosystem.
11) Static – klassengebunden statt objektgebunden
Felder und Methoden gehören normalerweise zu jedem Objekt. Mit dem Modifier static gehören sie stattdessen zur Klasse selbst – es gibt sie nur einmal, unabhängig von Objekten:
public class Auto { private static int anzahlAutos = 0; private String marke; public Auto(String marke) { this.marke = marke; anzahlAutos++; // klassenweiter Zähler } public static int getAnzahl() { return anzahlAutos; } } new Auto("BMW"); new Auto("VW"); System.out.println(Auto.getAnzahl()); // 2
Beachte den Aufruf: Auto.getAnzahl() – über den Klassennamen, nicht über ein Objekt. Genau das gleiche Prinzip wie bei Math.sqrt(...) oder Integer.parseInt(...): die Standard-Bibliothek nutzt static-Methoden überall.
12) Konstanten mit static final
Eine wichtige Kombination: static final erzeugt eine Konstante – einen Wert, der nur einmal existiert und nicht geändert werden kann:
public class PhysikKonstanten { public static final double PI = 3.14159265; public static final int MAX_GESCHWINDIGKEIT = 250; } // Nutzung: double umfang = 2 * PhysikKonstanten.PI * radius;
Konventionen für Konstanten in Java: Namen GROSS_GESCHRIEBEN mit Unterstrichen. Felder dieser Art sind oft public, weil sie sich nicht mehr ändern lassen – Kapselung ist hier unnötig.
13) toString, equals und hashCode
Jede Klasse erbt von Object (mehr dazu in L2). Drei Methoden werden in der Praxis fast immer überschrieben:
public class Auto { private String marke; private int baujahr; @Override public String toString() { return "Auto[" + marke + ", " + baujahr + "]"; } @Override public boolean equals(Object o) { if (!(o instanceof Auto)) return false; Auto other = (Auto) o; return marke.equals(other.marke) && baujahr == other.baujahr; } @Override public int hashCode() { return Objects.hash(marke, baujahr); } }
Wozu?
toString(): gibt eine lesbare String-Repräsentation – wird beimSystem.out.println(auto)und beim Debuggen verwendetequals(): definiert, wann zwei Auto-Objekte als „gleich" gelten – wichtig für Vergleich und CollectionshashCode(): für die effiziente Speicherung inHashMap,HashSetusw.
equals überschreibst, musst du immer auch hashCode überschreiben. Sonst funktionieren Collections wie HashMap nicht korrekt. Moderne IDEs generieren beide automatisch zusammen.
14) Häufige Fehler bei Anfängern
- Felder public statt private: Kapselung kaputt, schwer zu refaktorieren
- Konstruktor mit Rückgabetyp:
public void Auto(...)ist kein Konstruktor mehr, sondern eine normale Methode. Der Compiler warnt oft nicht - this.feld vergessen bei gleichnamigen Parametern:
marke = markeweist sich selbst zu, das Feld bleibtnull - == statt equals bei Strings und Objekten:
==prüft Referenzgleichheit, nicht inhaltliche Gleichheit - Vergessenes
new:Auto a;ist nur eine Variable, kein Objekt. Zugriff darauf gibtNullPointerException - Static-Felder als „globale Variablen" missbraucht: macht Code schwer testbar und unflexibel
15) Klassen-Datei und Package
In Java steht jede public Klasse in einer eigenen Datei, deren Name exakt dem Klassennamen entspricht: Auto.java. Mehrere Klassen werden in Packages (Verzeichnisse) organisiert:
package de.firma.fahrzeuge; public class Auto { // ... }
Die Package-Angabe steht oben in der Datei und muss zum Verzeichnis passen (src/de/firma/fahrzeuge/Auto.java). Klassen aus anderen Packages importiert man mit import de.firma.fahrzeuge.Auto;. Mehr zu Projekt-Struktur in L10.
Zusammenfassung
Eine Klasse ist der Bauplan, ein Objekt die konkrete Instanz davon, erzeugt mit new. Eine Klasse hat Felder (Daten) und Methoden (Verhalten), ein Konstruktor initialisiert beim new-Aufruf. Wichtigstes Prinzip ist Kapselung: Felder werden private deklariert, der Zugriff erfolgt nur über kontrollierte Getter/Setter, was Validierung und spätere Änderungen ermöglicht. Java kennt vier Sichtbarkeits-Modifier (private, default, protected, public); static bindet Felder/Methoden an die Klasse statt an einzelne Objekte, static final erzeugt Konstanten. Bei jeder Klasse sollte man zumindest toString() sinnvoll überschreiben, bei Collections-Nutzung auch equals() und hashCode() gemeinsam.
