Javaschubla.de - Java als erste Programmiersprache

Strings sind immutable (unveränderlich).

In OO05 haben wir gesehen, dass Objekte by reference als Parameter an Methoden übergeben werden (bzw. ihre Adresse by value, wenn man es anders betrachtet), d.h. wenn man sie in der aufgerufenen Methode verändert, ändert sich auch das ursprüngliche Objekt. Wer das mit Strings probiert, denkt vielleicht, Strings wären doch keine richtigen Objekte. Ein Beispiel:

class StringUebergabe
{
  public static void main(String[] args)
  {
    String s1 = "abc";
    dAnhängen(s1);
    System.out.println(s1); // immer noch abc
  }

  static void dAnhängen(String s);
  {
    s += 'd';
  }
}

Warum ist s1 immer noch abc, obwohl Strings Objekte sind, also by reference übergeben werden? s += 'd' ist eine Kurzschreibweise für s = s + 'd'. Es wird also der String s genommen, 'd' angehängt - man erhält also "abcd", und dieser neue String wird s zugewiesen. In s ist nun die Adresse zu einem anderen Stringobjekt als in s1 gespeichert. s ist zwar am Ende von dAnhängen sehr wohl "abcd". Aber wie wir in OO05 gesehen haben, wird bei der Zuweisung eines neuen Objekts (bzw. Zuweisung einer neuen Adresse) an die Parametervariable nichts an dem alten Objekt geändert.

Ein anderes Beispiel (vergleiche die API-Dokumentation von String.replace):

class StringUebergabe2
{
  public static void main(String[] args)
  {
    String s1 = "abc";
    bErsetzen(s1);
    System.out.println(s1); // immer noch abc
  }

  static void bErsetzen(String s);
  {
    s.replace('b', 'd');
  }
}

replace('b', 'd') ersetzt jedes 'b' im String durch ein 'd'.

Warum funktioniert es dann nicht? replace ändert nicht den ursprünglichen String s, sondern gibt einen neuen String zurück. Nicht nur s1 bleibt abc, auch s bleibt abc!

So wäre es richtig:

class StringUebergabe2
{
  public static void main(String[] args)
  {
    String s1 = "abc";
    s1 = bErsetzen(s1);
    System.out.println(s1); // immer noch abc
  }

  static String bErsetzen(String s);
  {
    return s.replace('b', 'd');
  }
}

Das hat also gar nicht viel mit der Übergabe eines Strings als Parameter an eine Methode zu tun, auch mit nur einer Methode wäre dasselbe passiert:

class StringReplace
{
  public static void main(String[] args)
  {
    String s1 = "abc";
    s1.replace('b', 'd');
    System.out.println(s1); // immer noch abc
  }
}

Strings sind immutable, sie verändern sich nie. Das heißt nicht, dass man einer Variable vom Typ String keinen neuen String zuweisen könnte. Natürlich kann man nach

    String s = "abc";

später immer noch

    s = "xyz";

aufrufen und es funktioniert. Genau so ist es trotzdem möglich

    s += 'd';

aufzurufen und man erhält wie gewünscht, dass s den Wert "abcd" annimmt. Aber s ist nicht mehr dasselbe Objekt. Es enthält nun eine andere Adresse.

Zur Verdeutlichung:

class StringImmutable
{
  public static void main(String[] args)
  {
    String s1 = "abc";
    String s2 = s1;
    s2 += 'd';
    System.out.println(s1); // immer noch "abc"
  }
}

Vergleiche hingegen ein normales, nicht immutable Objekt:

class AngestellterMutable
{
  public static void main(String[] args)
  {
    Angestellter a1 = new Angestellter("Petra", "Müller", 48, 1800);
    Angestellter a2 = a1;
    a2.setNachname("Schulz");
    System.out.println(s1.getNachname); // auch "Schulz"!
  }
}

a1 und a2 sind dasselbe Objekt (bzw. zwei Referenzen auf dasselbe Objekt, sie enthalten dieselbe Adresse).

Oben bei den Strings sind s1 und s2 auch dasselbe Objekt, aber nach s2 += 'd' ist s2 ein anderes Objekt als s1.


Übung

Probier mit den String-Methoden etwas herum.


In der nächsten Lektion lernst du, wie man aus Dateien liest.