Fireplace April 2026

Java Immutable vs Mutable

Tumbleweed

Captain
Registriert
März 2008
Beiträge
3.600
Bei meinem aktuellen Projekt bin ich auf die Frage gestoßen, ob ich ein oft verwendetes und sich ständig veränderndes Objekt mutable oder immutable gestallten sollte. Und zwar handelt es sich konkret um ein Objekt, das ich Vector2D getauft habe und welches hauptsächlich X- und Y-Koordinaten und ein paar Vektorfunktionen wie dot product und Normalisieren enthält.

Ich habe es erst einmal mutable gestaltet, d.h. x und y können von außen beschrieben werden. Damit habe ich mir allerdings auch schon erste Bugs eingefangen. Ich habe mir z.B. eine Reihe von Konstanten angelegt wie
public static final Vector2D ZERO = new Vector2D(0, 0);
public static final Vector2D WEST = new Vector2D(-1, 0);
public static final Vector2D EAST = new Vector2D(1, 0);
public static final Vector2D NORTH = new Vector2D(0, -1);
public static final Vector2D SOUTH = new Vector2D(0, 1);
public static final Vector2D NORTH_EAST = new Vector2D(1, -1);
public static final Vector2D NORTH_WEST = new Vector2D(-1, -1);
public static final Vector2D SOUTH_EAST = new Vector2D(1, 1);
public static final Vector2D SOUTH_WEST = new Vector2D(-1, 1);
um leichter Richtungsangaben formulieren zu können. Nun war ich so clever einfach irgendwo im Programm einem Objekt genau so eine Konstante zu übergeben und habe dabei nicht bedacht, dass die darin enthaltenen Attribute natürlich nicht automatisch auch konstant sind. Den Rest kann man sich denken :D
Die einfache Lösung war ein copy constructor und die Erzeugung eines neuen Vector2D-Objekts, bei erster Übergabe.

Nun bin ich aber am überlegen, ob der Performancegewinn der wegfallenden ständigen Objekterzeugung diese Fehleranfälligkeit rechtfertigt. In Effective Java wird ja z.B. geraten so viel wie möglich immutable zu halten, aus verschiedenen Gründen. Ich frage mich aber, wann wäre so ein Punkt erreicht, wo es wirklich kritisch wird für die Performance. So ein Vector2D-Objekt ist winzig klein und daher überlege ich, es nun doch immutable zu machen und dann eben ständig (also hunderte bis tausende Male pro (game-loop) tick) neu zu erzeugen.

Bin gespannt auf Meinungen dazu. Mal wieder so eine typische good-practice Frage von mir. :freaky:
 
Probier's erst mal mit immutablen Vektoren, Objekterzeugung in Java ist billig. Wenn das dir trotzdem die Performance verhagelt, dann kannst du es immer noch umstellen.
 
NullPointer schrieb:
Probier's erst mal mit immutablen Vektoren, Objekterzeugung in Java ist billig. Wenn das dir trotzdem die Performance verhagelt, dann kannst du es immer noch umstellen.

Das dürfte der gängige Ansatz sein, wobei der Anwendungsfall die Notwendigkeit für Optimierungen vermutlich hergibt. Aber es dürfte oftmals einfacher sein, konkrete Messungen mit einem realen System durchzuführen, als sich im Vorfeld allzu viele theoretische Gedanken zu einzelnen Performanzkriterien zu machen.
 
Hm ja das ist dann wohl so ein Grenzfall. Ich werde es erst mal auf immutable umstellen und die Sache im Hinterkopf behalten. Danke für die Meinungen. ;)
 
In der Regel ist die sache recht einfach.
Hardware ist Günstier als der Entwickler. Wenn das Projekt einmal so groß wird das Performance wird wo es schon schwer wird das ganze mit replikation zu handeln schauts natürlich anders aus.

Denk mal bei dir gehts um eine übungs projekt daher spars dir.

Vielleicht machst einfach
public static Vector2D getZeroVector2d(){
return new Vector2D(0, 0);
}
 
Also in dem Buch "Java Concurrency in Practice" steht, dass die Objekterzeugung in modernen JVMs nur noch eine Hand voll Maschinenoperationen benötigt und somit nicht mit malloc() vergleichbar ist. Bei Interesse schlage ich nochmal genau nach ;)
 
Mir schwirrt auch noch sowas im Kopf rum. Zum Thema object pooling hatte ich das damals aufgeschnappt und da wurde auch gesagt, dass die Erzeugung von Objekten auf modernen VMs so schnell ist, dass object pooling sich nicht mehr bzw. nur bei riesigen Objekten lohnt.

Wen dem so ist, kann ich ja beruhigt schlafen. :D

Rein technisch würde mich aber mal interessieren, wo der Unterschied zu malloc liegt. Bin nicht so der C-Mensch, aber dass man damit Speicher (im Heap?) reserviert, ist mir geläufig. Frage mich nur was eine VM da anders macht. Selbst wenn sie den Speicher im eigenen vorher reservierten Heap reserviert, ist doch die Tätigkeit die gleiche.
 
Zuletzt bearbeitet:
Die JVM hat einen eigenen Object-Pool, der recht effizient ist. Wenn ich mich recht entsinne, sogar für die einzelnen Threads, damit keine Synchronisierung beim "Erzeugen" von Objekten stattfinden muss ;)
Dadurch wird eben bei der "Objekterzeugung" nicht explizit Speicher angefordert, sondern im Object-Pool nachgesehen. Ist da kein Objekt welches man recyclen kann, wird ein neues angelegt, aber auch nur in schon allokierten Speichern. Speicher wird dann immer im Hintergrund allokiert.
 
Zurück
Oben