static
Zweck: Ermöglicht den Zugriff auf ein Feld oder eine Methode ohne Erstellung eines Objekt der Klasse. Gehört zur Klasse selbst und nicht zu einem spezifischen Instanz.
Anwendung:
- Globale Konstanten (
static final) - Hilfsmethoden (
Math.max,Collections.sort) - Zähler und Factory-Methoden
Beispiel:
class Counter {
static int count = 0; // gemeinsam für alle Objekte
public Counter() { count++; }
}
Counter c1 = new Counter();
Counter c2 = new Counter();
System.out.println(Counter.count); // 2💡 Besonderheiten:
staticVariablen werden einmal beim Klassenladen erstellt.- Auf
thisodersuperkann in einerstaticMethode nicht zugegriffen werden. - Wird oft für Singleton und Utility Klassen verwendet.
final
Zweck: Fixiert einen Wert oder verhindert Änderungen des Verhaltens.
Anwendung:
- Variable → kann nicht neu definiert werden.
- Methode → kann nicht in Subklassen neu definiert werden.
- Klasse → kann nicht abgeleitet werden.
Beispiele:
final int MAX = 10; // Konstante
// MAX = 15; // Fehler
final class Utils {} // kann nicht abgeleitet werden
class Parent {
final void greet() { System.out.println("Hi"); }
}
class Child extends Parent {
// void greet() {} // Fehler — Methode final
}💡 Tipp:
final wird oft mit static kombiniert → public static final = Konstante (z.B. Math.PI).
this
Zweck: Referenz auf das aktuelle Objekt – wird innerhalb von Methoden oder Konstruktoren verwendet.
Beispiel:
class Person {
private String name;
public Person(String name) {
this.name = name; // "this" unterscheidet das Feld vom Parameter
}
public void print() {
System.out.println(this.name);
}
}💡 Besonderheiten:
this()kann verwendet werden, um einen anderen Konstruktor in derselben Klasse aufzurufen:
public Person() {
this("Default");
}- Auf
thiskann instaticMethoden nicht zugegriffen werden (da kein Objekt vorhanden ist).
super
Zweck: Wird verwendet, um auf Methoden und Konstruktoren der Elternklasse zuzugreifen.
Beispiel:
class Animal {
void speak() { System.out.println("Animal speaks"); }
}
class Dog extends Animal {
void speak() {
super.speak(); // Aufruf der Methode der Elternklasse
System.out.println("Dog barks");
}
}💡 Besonderheiten:
super()muss die erste Zeile im Konstruktor sein.- Hilft bei der Überschreibung von Methoden und bei der Initialisierung von Subklassen.
volatile
Zweck: Wird für Variablen verwendet, die von mehreren Threads zugänglich sind. Garantiert, dass alle Threads den aktuellen Wert aus dem Speicher lesen und nicht aus dem Cache der Prozessor.
Beispiel:
class FlagExample {
private volatile boolean running = true;
void stop() {
running = false;
}
void run() {
while (running) {
}
}
}💡 Ohne volatile kann ein anderer Thread die Änderung der Variablen nicht sehen,
da sie möglicherweise im CPU-Cache gespeichert ist.
📍 Verwende volatile, wenn die Variable nicht vom vorherigen Zustand abhängt (z.B. ein boolean-Flag).
transient
Zweck: Gibt an, dass ein Feld nicht serialisiert werden muss. Beim Speichern eines Objekts (z.B. in einer Datei oder über ein Netzwerk) wird dieses Feld übersprungen.
Beispiel:
class User implements Serializable {
private String username;
private transient String password; // wird nicht serialisiert
}💡 Das Feld transient wird nach der Deserialisierung zu null oder 0.
📍 Wird bei der Arbeit mit Serializable und Sicherheit (Passwörter, Schlüssel) verwendet.
Unterschied zwischen == und .equals()
| Vergleich | Was tut es? | Wo wird es verwendet? |
|---|---|---|
== | Vergleicht Referenzen (Adressen im Speicher) | Objekte, Primitive |
.equals() | Vergleicht den Inhalt | Wird in Klassen überschrieben (String, Integer, etc.) |
| Beispiel: |
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false (verschiedene Objekte)
System.out.println(a.equals(b)); // true (gleicher Inhalt)💡 Für Primitive vergleicht == die Werte, für Objekte die Referenzen.
📍 Tipp:
- Bei Strings, Collections und Objekten sollte immer
.equals()verwendet werden. - Überschreibe
.equals()immer zusammen mithashCode().
String, StringBuilder, StringBuffer
String
- Unveränderliches (immutable) Objekt.
- Jede Konkatenationsoperation erzeugt ein neues Objekt im Speicher.
String s = "Hello";
s += " World"; // ein neues Objekt wird erstellt📍 Wird verwendet, wenn sich die Zeichenkette nicht oft ändert.
⚠️ Vermeide die Konkatenation von String in einer Schleife – es wird viel Garbage für den GC erzeugt.
StringBuilder
- Veränderliches (mutable).
- Nicht synchronisiert → schneller, aber nicht thread-sicher.
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Hello World📍 Wird in Single-Thread-Operationen verwendet.
StringBuffer
- Fast das Gleiche wie
StringBuilder, aber synchronisiert (thread-sicher). - Etwas langsamer.
StringBuffer sb = new StringBuffer("Hi");
sb.append(" there");
System.out.println(sb);📍 Wird in einer Multi-Thread-Umgebung verwendet, wenn Strings gleichzeitig von verschiedenen Threads bearbeitet werden.
🧩 Vergleich
| Klasse | Veränderlichkeit | Thread-Sicherheit | Geschwindigkeit | Wann verwenden? |
|---|---|---|---|---|
String | immutable | ✅ sicher | 🐢 langsam bei häufigen Änderungen | Statische Texte, Schlüssel |
StringBuilder | ✅ veränderlich | ❌ nicht | ⚡ schnell | Generierung von Strings, Muster |
StringBuffer | ✅ veränderlich | ✅ ja | ⚖️ mittel | Bei Multi-Threading |
⚙️ Best Practices
- ✅ Verwende
StringBuilderfür Konkatenationen in Schleifen. - ✅ Vergleiche Strings immer mit
.equals()und nicht mit==. - ✅ Mache Konstanten mit
public static final. - ✅ Verwende
volatilenur bei Bedarf für Synchronisierung. - ✅ Denk daran:
transientschützt Daten bei der Serialisierung. - ✅ Missbrauche
staticnicht – es reduziert die Testbarkeit.