Java - Member als transient markieren


Anwendungsfall: Du möchtest ein Objekt serialisieren


 (aka in einen Byte-Array umwandeln, um es z. B. per Netzwerk zu verschicken). Alle als "transient" markierten Member werden nicht mitserialisiert. Das bedeutet, dass auf der "anderen Seite", wo der Byte-Array wieder zu einem Objekt gemacht wird (Deserialisierung), das entsprechende Member null sein wird, auch wenn es vorher zum Zeitpunkt der Serialisierung einen Wert gehabt haben sollte. Bei der Deserialisierung wird der Konstruktor nicht aufgerufen. In einem solchen Szenario kann sich die Klassenimplementierung eben nicht sicher sein, ob transiente Member nicht null sind. Die gängige Lösung ist, einen initialisierenden getter (siehe oben) zu schreiben und den Zugriff auf transiente Member immer über den getter zu machen. Das vermeidet NullPointerExceptions.

Praxisbeispiel: Java-Enterprise mit Hibernate und getrennten Servern für Webfrontend und Geschäftslogik


Wenn du von deinem Webfrontend Datenbankobjekte an den Geschäftsserver sendest, werden diese serialisiert. Es ist nicht unüblich, dass diese Objekte spezielle Schlüssel enthalten, die transient sind, und auf der anderen Seite neu berechnet werden müssen. Die Klasse weiß aber nicht (soll sie auch nicht), auf welcher Seite der Anwendung sie gerade benutzt wird. Die Implementierung muss diesem Umstand Rechnung tragen. Der Schlüssel wird in seinem Getter generiert, wenn er null sein sollte. Nicht im Konstruktor.

Ganz anderes Beispiel: Du schreibst eine Anwendung auf Basis von Eclipse RCP. Die Fenster (Views) deiner Anwendung werden vom RCP-Framework instanziiert und wieder verworfen. Du hast keinen direkten Einfluss darauf, wann welcher Konstruktor aufgerufen wird und wann Instanzen wieder verworfen werden. Laufzeitabhängige Werte sollte man in diesen Views on demand (lazy) initialisieren und nicht im Konstruktor.

Statische Member


Statische Member: Statische Member sind keine sog. Instanzvariablen. Sie gehören zur Klasse, nicht zu deren Instanzen. Werden ihre Werte geändert, ändern sich die Werte dieses Members in allen (!) Instanzen der Klasse.
Kurz: Wenn irgendein Programmteil zur Laufzeit die Werte von statischen Membern ändert, arbeiten alle Instanzen dieser Klasse mit den neuen Werten, ohne, dass sie die Änderung selbst angestoßen hätten oder davon etwas mitbekommen würden. Wenn das Verhalten deines Codes vom aktuellen Wert dieses Members abhängt, hängt es damit insbesondere davon ab, welchen Wert andere Leute irgendwann vorher mal irgendwie für dieses Member gesetzt haben.

Das ruft meist sehr seltsame Seiteneffekte hervor und lässt sich unheimlich schlecht debuggen. Klassen haben keinen Zustand, Instanzen schon. Speichere Zustände (änderbare Werte) nicht in statischen Membern.

Statische Member sind für Konstanten (static final) gut und evtl. für Singletonkram. Ansonsten sollte man sie meiden. Sie werden meist als Ersatz für Globale Variablen missbraucht oder, um den Zugriff auf wichtige Sachen zu erleichtern. Tu das nicht, ohne genau zu wissen, was du tust! Globale Variablen sind böse, weil jeder Zugriff auf sie hat und dadurch besagte Seiteneffekte hervorrufen kann.

Frameworks wie Log4J oder Mockito nutzen solcherlei Dinge. Deren Enwickler wissen aber 1. was sie tun und der Code ist 2. mittlerweile recht oldschool.