1. Was sind Getter und Setter
Wenn man sich ein Objekt als Safe vorstellt, dann sind seine privaten Felder der Inhalt des Safes, und Getter und Setter sind die Schlüssel zu einzelnen Fächern. Getter erlauben herauszufinden, was drin liegt, und Setter legen vorsichtig etwas Neues hinein (aber bitte keinen Igel statt der Dokumente).
Getter
Ein Getter ist eine öffentliche Methode (public), die den Wert eines privaten Feldes (private) zurückgibt. Üblicherweise beginnt sein Name mit get + Feldname mit großem Anfangsbuchstaben.
public class Person {
private String name; // Privates Feld
// Getter für das Feld name
public String getName() {
return name;
}
}
Setter
Ein Setter ist eine öffentliche Methode (public), die erlaubt, den Wert eines privaten Feldes zu ändern. Sein Name beginnt mit set + Feldname mit großem Anfangsbuchstaben.
public class Person {
private String name;
// Setter für das Feld name
public void setName(String name) {
this.name = name;
}
}
Für boolean-Felder
Für Felder vom Typ boolean verwendet man in Gettern das Präfix is:
private boolean active;
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
2. Syntax und Namenskonventionen
Java ist eine strenge, aber keine pingelige Sprache. Es gibt etablierte Konventionen, die Ihren Code für andere Entwickler verständlich machen (und für Sie selbst in einem Monat).
- Getter: public Type getFieldName()
- Setter: public void setFieldName(Type value)
- Getter für boolean: public boolean isFieldName()
Der Feldname wird im Methodennamen mit großem Anfangsbuchstaben geschrieben: Wenn das Feld age heißt, dann lauten die Methoden getAge() und setAge().
Diese Konvention folgt dem JavaBeans-Stil, wodurch IDEs, Bibliotheken und Frameworks Ihre Getter und Setter automatisch finden können. Wenn Sie beispielsweise Spring oder JavaFX verwenden, werden diese Methoden „magisch“ aufgerufen, wenn es nötig ist.
3. Codebeispiele
Nehmen wir ein Übungsprojekt – eine einfache „Kontakte“-App (analog zu einem Telefonbuch) – und fügen dort korrekte Getter und Setter hinzu.
Beispiel: Klasse Contact mit privaten Feldern und Gettern/Settern
public class Contact {
private String name;
private String phone;
private int age;
private boolean favorite;
// Getter
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
public int getAge() {
return age;
}
public boolean isFavorite() {
return favorite;
}
// Setter
public void setName(String name) {
this.name = name;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setAge(int age) {
// Validierungsbeispiel: Das Alter darf nicht negativ sein
if (age < 0) {
System.out.println("Das Alter darf nicht negativ sein!");
return;
}
this.age = age;
}
public void setFavorite(boolean favorite) {
this.favorite = favorite;
}
}
Verwendung in der Anwendung
Contact friend = new Contact();
friend.setName("Ivan Ivanov");
friend.setPhone("+1-999-123-45-67");
friend.setAge(25);
friend.setFavorite(true);
System.out.println("Name: " + friend.getName());
System.out.println("Telefon: " + friend.getPhone());
System.out.println("Alter: " + friend.getAge());
System.out.println("Favorit: " + (friend.isFavorite() ? "Ja" : "Nein"));
Validierungsbeispiel im Setter
Beachten Sie, dass wir im Setter setAge eine einfache Prüfung hinzugefügt haben: Wenn das Alter negativ ist, ändern wir das Feld nicht und geben eine Warnung aus. Das ist eine einfache Möglichkeit, das Objekt vor inkorrekten Daten zu schützen.
4. Best Practices: so machen Sie es richtig
Nicht alle Felder sollten öffentliche Setter haben
Manchmal soll ein Feld nur lesbar sein – zum Beispiel eine eindeutige ID, die bei der Objekterzeugung gesetzt wird und sich nicht mehr ändert. In so einem Fall schreibt man einfach keinen Setter:
public class Contact {
private final int id; // final – nach der Initialisierung nicht mehr veränderbar
public Contact(int id) {
this.id = id;
}
public int getId() {
return id;
}
// Kein setId!
}
Verwenden Sie Getter/Setter für Zugriffskontrolle und Validierung
public void setName(String name) {
if (name == null || name.trim().isEmpty()) {
System.out.println("Der Name darf nicht leer sein!");
return;
}
this.name = name;
}
Geben Sie interne veränderliche Objekte nicht direkt preis
Wenn Sie ein Feld haben – zum Beispiel ein Array von Telefonnummern:
private String[] phones;
Geben Sie es nicht direkt über den Getter zurück:
public String[] getPhones() {
return phones; // Schlecht!
}
Solcher Code erlaubt externem Code, die Sammlung nach Belieben zu verändern – und verletzt damit die Kapselung!
Besser: eine Kopie des Arrays zurückgeben:
public String[] getPhones() {
return Arrays.copyOf(phones, phones.length); // Wir geben eine Kopie zurück
}
Oder einfach klonen:
public String[] getPhones() {
return phones.clone();
}
Machen Sie Getter und Setter verständlich und einfach
- Schreiben Sie keine komplexe Businesslogik in Getter/Setter – ihre Aufgabe ist simpel: Zugriffskontrolle und bei Bedarf Validierung.
- Wenn sich ein Feld nicht ändern soll, schreiben Sie überhaupt keinen Setter.
- Wenn ein Feld von außen nicht zugänglich sein soll, schreiben Sie keinen Getter.
5. Automatische Generierung von Gettern/Settern in der IDE
Accessor-Methoden von Hand zu schreiben ist nicht gerade vergnüglich, besonders wenn eine Klasse dutzende Felder hat. Zum Glück können moderne IDEs (z. B. IntelliJ IDEA, Eclipse, VS Code mit Plugins) sie automatisch generieren.
In IntelliJ IDEA
- Öffnen Sie die Klasse und setzen Sie den Cursor in den Klassenrumpf.
- Drücken Sie Alt + Insert (oder Code -> Generate...).
- Wählen Sie Getter and Setter.
- Markieren Sie die gewünschten Felder und klicken Sie auf OK.
Voilà! Ihre Getter und Setter erscheinen wie von Zauberhand.
In Eclipse
- Öffnen Sie die Klasse.
- Rechtsklick – Source – Generate Getters and Setters...
- Wählen Sie die Felder und klicken Sie auf OK.
In VS Code (mit Java Extension Pack)
- Öffnen Sie die Klassendatei.
- Geben Sie in der Befehlspalette (Ctrl+Shift+P) Generate getters and setters ein.
- Folgen Sie den Anweisungen.
6. Ihr Projekt weiterentwickeln: Kapselung in Aktion
In den vorherigen Vorlesungen haben Sie eine einfache Anwendung zum Speichern von Kontakten aufgebaut. Jetzt können wir sie verbessern, indem wir die Felder privat machen und den Zugriff nur über Getter/Setter erlauben.
Vorher (schlechtes Beispiel):
public class Contact {
public String name;
public String phone;
public int age;
}
Problem: beliebiger Code kann Folgendes tun:
Contact c = new Contact();
c.age = -1000; // Jetzt haben wir einen Vampir im Telefonbuch!
Nachher (gutes Beispiel):
public class Contact {
private String name;
private String phone;
private int age;
public void setAge(int age) {
if (age < 0) {
System.out.println("Das Alter darf nicht negativ sein!");
return;
}
this.age = age;
}
public int getAge() {
return age;
}
// Weitere Getter/Setter...
}
Nun ist es unmöglich, das Objekt von außen versehentlich (oder absichtlich) zu beschädigen.
7. Getter/Setter für berechnete und unveränderliche Eigenschaften
Manchmal wird der Wert nicht in einem Feld gespeichert, sondern bei Bedarf berechnet:
public class Rectangle {
private int width;
private int height;
public int getArea() {
return width * height;
}
}
Ein Setter für die Fläche ist nicht nötig – sie lässt sich nicht direkt setzen, sondern nur durch Ändern der Breite oder Höhe.
8. Getter und Setter: typische Fehler
Fehler Nr. 1: Getter/Setter verletzen die Kapselung.
Wenn ein Getter eine Referenz auf ein internes veränderliches Objekt zurückgibt (z. B. auf eine Liste), kann externer Code es verändern und dabei alle Prüfungen umgehen. Das untergräbt die Idee der Kapselung.
Fehler Nr. 2: Der Setter validiert die Daten nicht.
Wenn ein Setter einfach nur zuweist, ohne zu prüfen, kann das zu einem inkorrekten Objektzustand führen (z. B. negatives Alter oder leerer Name).
Fehler Nr. 3: Automatische Generierung von Settern für alle Felder.
Eine IDE kann Setter für alle Felder generieren, aber das ist nicht immer richtig! Für einen Bezeichner wie id ist ein Setter zum Beispiel nicht nötig.
Fehler Nr. 4: Komplexe Logik in Gettern/Settern.
Getter und Setter sollten einfach sein. Wenn dort komplexe Businesslogik auftaucht, sollte man sie in eigene Methoden auslagern.
Fehler Nr. 5: Verstoß gegen Namenskonventionen.
Wenn man einen Getter fetchName() statt getName() nennt, können manche Frameworks und Bibliotheken ihn nicht erkennen.
GO TO FULL VERSION