# Klasse Immutable



## javacup (21. Mai 2010)

Hallo ,
ich bin mir gerade nicht sicher dem Entwurfsmuster "Immutable". Kann eine solche Klasse ein privates nicht finales Attribut haben, das sich manchmal ändert. Kann ich in einer "immutablen" Klasse beispielsweise das Attribut

```
private int methodenaufrufe=0;
```
benutzten, das jedes mal um eins erhöht wird, wenn irgendeine Methode der Klasse aufgerufen wird? Es zählt also die Methodenaufrufe. Der Benutzter kann dieses Attribut nicht bewusst ändern. Es wird auch nicht verwendet beim Berechnen des Hash-Wertes und beim Vergleichen mit anderen Objekten.
Ist die Klasse immer noch "immutable"?


----------



## Der Müde Joe (21. Mai 2010)

entscheide du:
Immutable Objects (The Java™ Tutorials > Essential Classes > Concurrency)



> An object is considered immutable if its state cannot change after it is constructed.


----------



## javacup (21. Mai 2010)

Ok, danke schonmal.
Mein Objekt wäre also technisch nicht immutable. Hat es dadurch irgendwelche Nachteile gegenüber richtigen "immutablen" Objekten?


----------



## FArt (21. Mai 2010)

"technisch nicht" immutable? "richtig" immutable?
Entweder es ist unveränderbar oder nicht, dazwischen gibt es nichts. Die Nachteile sind dann das Gegenteil der Vorteile, die z.B. in Joes Link aufgeführt werden.


----------



## Landei (21. Mai 2010)

Wenn sich ein Objekt wie ein immutables Objekt verhält und von außen auf keine Weise Unterschied festzustellen ist, dann ist es für mich ein immutables Objekt.

Als Beispiel sei Lazy Initialization genannt. Angenommen ich habe ein wirklich großes oder kompliziertes Objekt (z.B. einen Graphen mit mit ein paar tausend Knoten), das eventuell in eine HashMap gepackt werden soll. Den Hashwert davon zu berechnen ist dann eine aufwendige Operation, die ich vermeiden will, wenn ich sie nicht benötige. Also würde ich schreiben:


```
class Foo {

   private Integer hashValue = null;

   public int hashCode() {
      if (hashValue == null) {
         hashValue = ergebnisEinerLangwierigenBerechnung();
      }
      return hashValue; 
   }
}
```

Strenggenommen ist Foo kein unveränderliches Objekt, es ändert seinen inneren Zustand. Aber trotzdem wäre es für die Außenwelt immutable, weil man keinen Unterschied feststellen könnte (Achtung: Mein einfaches Foo-Beispiel müsste ich dazu noch thread-safe machen).


----------



## ice-breaker (21. Mai 2010)

Landei hat gesagt.:


> Wenn sich ein Objekt wie ein immutables Objekt verhält und von außen auf keine Weise Unterschied festzustellen ist, dann ist es für mich ein immutables Objekt.



nach "Java Concurrency in Practice" auch


----------



## maki (22. Mai 2010)

> Strenggenommen ist Foo kein unveränderliches Objekt, es ändert seinen inneren Zustand.


Wobei sich der Zustand des  hashcodes eigentlich nur von "nicht-initialisiert" auf "initialisiert" ändert, lazy-init ist kein Problem für Immutable Objekte, sondern ein Vorteil davon.
Bei dem "methodenaufrufe" Beispiel ist das anders.


----------



## ice-breaker (22. Mai 2010)

Der Status des Objektes mag sich streng genommen ändern, er beeinflusst jedoch nicht das Verhalten (Methoden) und der verändere Status lässt sich auch nicht auslesen oder verändern (Getter und Setter).
Streng genommen ist dieses Attribut also sowieso unnütz.


----------



## Illuvatar (22. Mai 2010)

Also zum Beispiel von Anfang würd ich sagen:
Entweder das Attribut beeinflusst das Verhalten des Objekts nicht. Dann könnte man es eigentlich auch gleich weglassen, und ich würde das Ding schon immutable nennen.
Aber man baut doch keinen Counter in seine Klasse, wenn der dann nichts bewirkt? Und wenn doch... dann ist es eben nicht immutable


----------



## maki (22. Mai 2010)

Wertobjekte sind immer gute Kandidaten für Immutables, diese haben wenig Logik und ihre Identität hängt von ihren Werten ab.

Wenn Immutables allerdings Refrenzen halten auf mutable Objekte, sind sie selber keine Immutables mehr.
Meistens geht man umgekehrt vor, so das ein Objekt mit viel Logik mutable ist, und Referenzen hält auf Immutable Objekte.


----------



## Landei (22. Mai 2010)

maki hat gesagt.:


> Wertobjekte sind immer gute Kandidaten für Immutables, diese haben wenig Logik und ihre Identität hängt von ihren Werten ab.



Das ist eine Sichtweise, die sich oft in der OO-Welt findet. Dabei können gerade komplexe Objekte von Unveränderbarkeit profitieren. Ich halte z.B. Collections für gute Kandidaten. Damit meine ich nicht etwa das unbrauchbare Collections.unmodifiable... Zeug, sondern Sachen wie pcollections oder functional java. In Scala geht meine Verwendung veränderlicher Collections inzwischen gegen null. Generell verwende ich dort bestimmt zu 95% unveränderliche Objekte, und mein Code ist dadurch nicht langsamer geworden, sondern einfacher und stabiler.


----------



## maki (23. Mai 2010)

Ja Landei, Copy-on-write ist 'ne gute Sache für Multiprozessorsysteme, aber mit "Objekte mit viel Logik" meinte ich keine Collections, denn diese sind für mich keine Objekte mit Logik oder komplex, können ruhig immutable sein, Zustände brauchen sie ja keine.


----------



## FArt (25. Mai 2010)

> Der Benutzter kann dieses (...private...) Attribut nicht bewusst ändern. Es wird auch nicht verwendet beim Berechnen des Hash-Wertes und beim Vergleichen mit anderen Objekten.
> Ist die Klasse immer noch "immutable"?


Nur mal nachgehackt... (lol, wollte ich auch mal schreiben)...
der Poster ging davon aus, dass sein Objekt aufgrund dieser Aussage immutable ist, was nicht stimmen muss. Es kommt nicht darauf an, ob das Attribut bewusst oder unbewusst geändert werden kann und privat ist, sondern ob die Änderung in irgendeiner Form sichtbar ist ... dazu kann auch interner Zustand zählen. Würdest du von einem immutable Objekt erwarten, dass sich die Ausgabe der toString() Methode ändert, z.B. weil sich der Methodenzähler erhöht hat? Oder sich Logausgaben der selben Methode ändern? Schwieriger sieht es aus, wenn ein Objekt serialisierbar ist. Und ganz schlimm sieht es aus, wenn dieser Satz nicht mehr stimmt: "Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.". Auch wenn der Status also nicht aktiv geändert werden kann, kann er in obigem Fall inkonsistent sein =>  nicht immutable.
... und sie dreht sich doch...


----------



## SlaterB (25. Mai 2010)

vielleicht reicht es, wenn ein Interface immutable ist, die Klasse also nur hinsichtlich bestimmter anderer Klassen und packages 
(die nur die public-Methoden sehen),
intern wird einiges verändert, worauf gewisse interne Kontrollstrukturen, Logging, Reflection-Zugriffe Rücksicht nehmen müssen, die können das Objekt nicht als Immutable ansehen,
der große Rest der 'normalen' Programmlogik muss sich für diesen Teil aber nicht interessieren


----------



## Empire Phoenix (25. Mai 2010)

Immutable objecte, hm enumerations sind in java classenverwand (soweit ich weiß setzt der compiler die sogar in eine Classe um)
Netzwerknachrichten, die festen inhalt haben und objectbasiert gemacht werden, sind normalerweise sinnvollerweise nicht vom Client veränderbar. So gesehen sind sie auf Clientseite immutable.


----------

