Strings unveränderlich????

TMT

Neues Mitglied
Ich habe gerade folgende Aussage gelesen.

Die Zeichenkette-Klasse in Java ist unveränderlich, was bedeutet, dass der Inhalt einer Zeichenkette nach der Erstellung nicht mehr geändert werden kann.
Das kann ich nicht so ganz glauben, denn:
Java:
String strValue = "Hallo";
        strValue = "Welt";

Oder was sagen andere dazu?
 
Du hast da eine Neuzuweisung an strValue. Der vorher mit der Variable strValue gespeicherte Wert (das String-Obj) ändert sich nicht und wird weggeworfen. Einen String kannst du nicht ändern, auch ein StringBuilder kann das nicht, weil die Klasse final ist und alle Attribute ebenso. Merke: Das String-Manging (hier umgang mit Variablen) ist etwas anderes als eine String-Manipulation.
 
Daraus lässt sich allerdings nicht schließen, dass der Inhalt einer Instanz dieser Klasse unveränderlich ist
doch, weil
Du kannst halt keine weiteren Klassen davon ableiten
die möglicherweise Attribute verändern könnten.

Oder einfacher gesagt, es gehört zum Immutable-Pattern dazu, dass auch die Klasse final ist.

Aber ich bin mir sicher, dass das bereits bewusst war und nur die richtige Formulierungsweise fehlte.
 
Das ist aber "nur" ein best Practice, wie es z.B. in Effective Java beschrieben wurde. Nur weil es eine abgeleitete Klasse geben kann, die nicht unveränderlich ist, ändert das ja nichts daran, dass die Klasse selbst unveränderlich ist. Wenn jemand Quatsch macht, dann macht diese Person eben Quatsch. Das hast Du aber generell - jeder Verstoss gegen Liskovs Substitution Principle ist nichts anderes: Der Contract der Basis Klasse wird verletzt.

Daher sind das durchaus zwei unterschiedliche Dinge, die man nicht durcheinander mischen sollte. Denn unter dem Strich besagt es nur, dass man Elemente, die man immutable haben will, final machen sollte. Da es in der Regel einfache Klassen sind, die eigene Werte beinhalten, ist das relativ einfach. Aber es ist zumindest denkbar, dass man eben doch eine Hirarchie braucht. Dann erbt B von A und beide sollen immutable sein. Dann kann aber A nicht final sein.
 
Das hat nichts mit Quatsch machen zu tun, sondern mit richtiger Programmierung
Ich denke, Du hast meine Aussage schlicht missverstanden. Von einer Klasse, die immutable ist und nicht final, zu erben und ihr dann einen veränderlichen State zu geben, verstößt gegen Liskovs Substitution Principle und ist damit in meinen Augen Quatsch und auf keinen Fall "richtige Programmierung".

Aber das muss man nicht diskutieren. Kernpunkt ist und war:
Immutable class bedeutet nicht zwingend, dass de class final ist. Sie sollte es sein, aber das ist keine zwingende Voraussetzung.
Und den Punkt haben wir dann ja jetzt wohl abgehakt, oder?
 
es gehört zum Immutable-Pattern dazu, dass auch die Klasse final ist.
Das Eine bedingt allerdings nicht das Andere. Deshalb ist deine Schlussfolgerung ganz einfach falsch.

Das kann ich dir auch beweisen:
Java:
public final class Mutabel {
   
    private int value;
   
    public void mutate(int value) {
        this.value = value;
    }
   
    public int getValue() {
        return value;
    }
}

Klasse final, Inhalt nicht. QED.

Ich bin sicher, dass weißt du auch. Immerhin ist der Inhalt des StringBuilders veränderbar. Erst die Instanz von String, die du z. B. mit toString() erhältst ist es nicht mehr.

Aber ich bin mir sicher, dass das bereits bewusst war und nur die richtige Formulierungsweise fehlte.
Meine Formulierung war genau so gemeint, wie sie geschrieben wurde.
Kernpunkt ist und war:
Immutable class bedeutet nicht zwingend, dass de class final ist.
Kernpunkt ist: Eine Klasse die final ist, muss nicht zwingend unveränderbar sein. 🙂 Und im Fall des oben genannten StringBuilders ist es schlicht auch falsch, weil er veränderbar ist.
 
Zuletzt bearbeitet:
Tatsächlich zwingend?
Ja sonst kann ich folgendes machen und die geerbte Klasse ist nicht mehr immutable;
Java:
class Immutable2 extends Immutable {
    public int wichtigerWert ;
 
    public Immutable2(int value) {
        super(value);
    }
 
    public void mutate(int value) {
        this.value = value; // Fehler!!!
    }

}
Aber versuche einmal die Klasse String zu erweitern.
Unveränderbar ist absolut. Deshalb darf es von einer unveränderbaren Klasse auch keine neue ( veränderte) Klasse geben.
 
Also das wird jetzt massive Wortklauberei.

Erst einmal müssen wir die Begriffe definieren. Schon, dass man von "immutable class" gesprochen hat, ist Quatsch. Immutable sind Objekte. Da kann man z.B. als Definition nehmen:
An immutable object is an object whose internal state remains constant after it has been entirely created
Immutable Objects in Java | Baeldung

Und wenn man den Baeldung Beitrag anschaut, dann sieht man auch ein Beispiel und da ist die Klasse schlicht nicht final. (Was ich nicht gut finde, denn eine Klasse sollte final sein. Aber hier ist es erst einmal schön, dass man so ein Beispiel findet.)

Ja sonst kann ich folgendes machen und die geerbte Klasse ist nicht mehr immutable;
Nein, wenn das Element private ist, dann kannst Du da keinen Wert in der abgeleiteten Klasse zuweisen.

Und die ganze Diskussion ist sinnlos. Es läuft also schlicht darauf hinaus: Wenn Du eine Klasse hast, mit der Du immutable Instanzen erzeugst, dann ist es ein Verstoß gegen Liskovs Substitution Principle, da sich die abgeleitete Klasse nicht mehr so verhält wie die Basisklasse. Und da spielt das final Schlüsselwort keine Rolle. Ich kann mit der final Klasse immer noch alles machen (wenn auch nicht mehr so einfach), wie Spring Framework und die Mockito Library zeigen (um zwei Beispiele zu bringen)

Und natürlich gibt es genug Quellen, die klar machen: So eine Klasse sollte final sein. Daher gibt es Blog Artikel, die das bei der Anleitung mitgeben (geeksforgeeks ist aber schlecht, die Formulierung ist aus meiner Sicht nicht ok. ("The class must be declared as final so that child classes can’t be created." - eben nicht! Das ist Anfänger Niveau wie es Tobias regelmäßig bringt, wo man einem Neuling ohne Begründung etwas als MUSS verkauft statt es vernünftig zu erläutern. Dann sollte etwas so sein aber Ausnahmen sind denkbar! Es geht um ein Verständnis!) Da finde ich dann Effective Java deutlich besser - klare Best Practices mit Erläuterung. Kann ic nur jedem empfehlen!)

Daher noch einmal ganz klar und deutlich: Wenn Ihr behauptet, etwas MUSS so sein, dann darf es unter keinen Umständen anders sein!

Das ist meine klare Sichtweise. Aber bestimmt habt Ihr da auch einfach mal ein paar Argumente?
 
Ach ja - wegen immutable class - das kann man natürlich 1:1 ebenso definieren. Dazu einfach aus Effective Java die folgende Definition:
An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is fixed for the lifetime of the object, so no changes can ever be observed.

Mit der Definition ist es übrigens prinzipiell von der Definition her auch kein Problem, wenn man hat:
public class NonImmutable extends Immutable

Immutable erfüllt ohne final die Definition. NonImmutable würde diese Definition nicht erfüllen. Daher halt mein Hinweis auf das Liskovsche Substitutionsprinzip.
 
Nein, wenn das Element private ist, dann kannst Du da keinen Wert in der abgeleiteten Klasse zuweisen.
Die Betonung hier liegt auf wenn. Jeder kann eine nicht finale Klasse benutzen und von dieser Klasse erben. Was daraus gemacht wird liegt nicht in der Hand des ursprünglichen Erstellers. Mittels final kann er das allerdings im Vorfeld unterbinden.

Bei Oracel findet man folgende Strategie für immutable Objekte.
https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
Daraus ergibt sich auch das die Klasse nicht zwingend final sein muss. Die Klasse muss aber verhindern, dass dann Unterklassen Methoden nicht überschreiben können.
Was somit @KonradN mit seinem Hinweis darauf bestätigt.
Siehe obigen Link unter Punkt 3)
Trotzdem wird das angeführte Beispiel als final Class gezeigt.
 
Die Betonung hier liegt auf wenn.
Ja, das ist richtig. Und ich denke, unter dem Strich sind wir alle hier durchaus einer Meinung oder liegen zumindest sehr dicht beieinander und wir reden teilweise leicht aneinander vorbei, weil vermutlich zwei Sichtweisen aufeinander Treffen:
Zum einen die Sichtweise: Wie sollte man eine immutable Klasse schreiben? Aus der Sicht kommen viele. Ich selbst hatte auf Grund der Posts #3 und #4 die Fragestellung: Was muss zwingend gegeben sein, damit man etwas als immutable bezeichnen kann?

Bezüglich diesem "wenn" macht es evtl. Sinn, da einfach einmal die Anforderungen zusammen zu fassen. Wie sollte eine immutable Klasse aussehen:

a) Keine Methoden anbieten, die den State verändern (Klar, Setter wären blöd)

b) final class -> Keine Ableitung erlauben, damit nicht eine nicht immutable Version übergeben werden kann, was dann zu Problemen führen kann.

c) Alle Felder final -> Initialisierung nur im Konstruktor möglich.

d) Alle Felder private -> Keine Veränderung außerhalb der Klasse möglich

e) Exklusiver Zugriff auf alle veränderlichen Komponenten. Man kann also gerne in der Klasse etwas vorhalten, das an sich verändert werden kann. Aber die Referenz kommt nicht von außen und wird auch nie nach außen gegeben. Also wenn man eine List hat, dann würde man nicht die Referenz von außen übernehmen sondern eine neue List erzeugen und die Elemente übernehmen. Ebenso wenn man es nach außen gibt.

Das findet sich an vielen Stellen beschrieben, u.a. im erwähnten Effective Java Buch aber auch im Link von @Blender3D in #10.
 
Und den Punkt haben wir dann ja jetzt wohl abgehakt, oder?
Da sind wir daccor.

Wenn jemand aber eine immutable Klasse schreiben möchte, also eine Klasse, deren Instanzen immutable sind, dann würde ich es nicht akzeptieren, wenn diese Klasse nicht den final Modifier hätte...

Aber wie auch richtig... da sind wir partiell bei Wortklauberei. Formulierungen sollten aber dennoch richtig sein. (Auch wenn jetzt ein Anfänger bzw eine Anfängerfrage mit den bisherigen Antworten überfordert sein könnte.) So, der Grill ruft
 
Ich habe gerade folgende Aussage gelesen.


Das kann ich nicht so ganz glauben, denn:
Java:
String strValue = "Hallo";
        strValue = "Welt";

Oder was sagen andere dazu?
Zwar OT, aber warst du nicht vor kurzem noch Dozent für Java mit langjährige Berufserfahrung und hast dich über deiner Meinung zu niedrige Jobangebote beschwert? 🤨
 
Ohne den Thread unnötig weiter führen zu wollen - ich bin da gerade durch Zufall über etwas stolpert als ich über den Source von BigInteger gekommen bin:
BigInteger vom Java Framework ist immutable und nicht final 🙂

jdk/BigInteger.java at master · openjdk/jdk · GitHub

(sehr stark verkürzter Auszug)
Java:
/**
 * Immutable arbitrary-precision integers.  All operations behave as if
 */

public class BigInteger extends Number implements Comparable<BigInteger> {
 
Ohne den Thread unnötig weiter führen zu wollen - ich bin da gerade durch Zufall über etwas stolpert als ich über den Source von BigInteger gekommen bin:
BigInteger vom Java Framework ist immutable und nicht final 🙂

Macht ja auch Sinn, die beiden Konzepte sind ja zwei unterschiedliche Dinge. Eine unveraenderbare Klasse kann auch Subklassen haben, wohingegen eine Klasse welche nicht vererbbar sein soll ja durchaus veraenderbar sein kann. Zu sagen dass eine unveraenderbare Klasse immer final sein muss ist ja nicht richtig. Ein anderes Beispiel dafuer ist ja java.nio.Path, da steht in der Dokumentation der Schnittstelle:

Code:
 * <h2>Concurrency</h2>
 * <p> Implementations of this interface are immutable and safe for use by
 * multiple concurrent threads.

Wir koennen eben nicht den gesamten "API-Vertrag" in der Sprache selbst abdecken, manchmal muss man auch auf die Javadoc ausweichen (und darauf vertrauen dass der Verwender halt nicht dumme Dinge tut, oder dann zumindest nicht heulend ankommt).

Meine Meinung ist ja ohnehin dass private und final ueberbewertet werden, aber das ist wahrscheinlich irgendwie ein anderes Thema...
 

Neue Themen


Zurück
Oben