Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage |
<< | < | > | >> | API | Kapitel 11 - Strings |
Beim Studium der Klassenbibliotheken erkennt man, daß die Klasse String mit dem Attribut final belegt ist. Einer der Gründe für diese Maßnahme ist die dadurch gesteigerte Effizienz beim Aufruf der Methoden von String-Objekten. Anstelle der dynamischen Methodensuche, die normalerweise erforderlich ist, kann der Compiler final-Methoden statisch kompilieren und dadurch schneller aufrufen. Daneben spielten aber auch Sicherheitsüberlegungen und Aspekte des Multithreadings eine Rolle.
Leider hat dies den großen Nachteil, daß aus der String-Klasse keine neuen Klassen abgeleitet werden können. Es gibt also keine Möglichkeit, die vorhandenen Methoden auf natürliche Art und Weise zu ergänzen oder zu modifizieren. Soll beispielsweise eine neue Methode replace geschrieben werden, die in der Lage ist, Strings (und nicht nur einzelne Zeichen) gegeneinander auszutauschen, so bleibt nur der Umweg über eine Methode einer anderen Klasse, die den zu modifizierenden String als Parameter übergeben bekommt. Alternativ könnte man natürlich auch die komplette String-Klasse neu schreiben. Leider sind beide Varianten unschön und konterkarieren die Vorteile der objektorientierten Implementierung von Zeichenketten in Java. |
|
In Java gibt es an vielen Stellen Verbindungen zwischen dem Compiler und der Laufzeitbibliothek, und zwar insofern, als der Compiler Kenntnis über interne Eigenschaften bestimmter Klassen hat und die Fähigkeit besitzt, Instanzen dieser Klassen zu erzeugen und zu manipulieren. So ist er beispielsweise in der Lage, Code zu generieren, um String-Objekte zu erzeugen, einander zuzuweisen oder mit Hilfe des +-Operators zu verketten.
Jedes String-Literal ist eine Referenz auf ein Objekt der Klasse String. Wenn der Compiler beim Übersetzen des Quelltextes ein String-Literal findet, erzeugt er ein neues String-Objekt und verwendet es anstelle des Literals.
In Java ist der Operator + auch auf Strings definiert. Auf zwei String-Objekte angewendet, liefert er die Verkettung beider Objekte, d.h. ihre Hintereinanderschreibung. Eine Möglichkeit, die String-Verkettung zu übersetzen, könnte darin bestehen, ein temporäres StringBuffer-Objekt zu konstruieren und die Operanden mit Hilfe der append-Methode anzuhängen. Das resultierende Objekt könnte dann mit der toString-Methode effizient in einen String konvertiert werden. Die Klasse StringBuffer dient dazu, veränderliche Strings zu implementieren. Sie wird im nächsten Abschnitt vorgestellt.
Diese Vorgehensweise soll an dem folgenden Beispiel erläutert werden. Das Programm gibt zweimal hintereinander »Hallo, Welt« aus. Beim ersten Mal wird der +-Operator verwendet, beim zweiten Mal die Variante mit dem temporären StringBuffer-Objekt:
001 /* Listing1103.java */ 002 003 public class Listing1103 004 { 005 public static void main(String[] args) 006 { 007 String a, b, c; 008 009 //Konventionelle Verkettung 010 a = "Hallo"; 011 b = "Welt"; 012 c = a + ", " + b; 013 System.out.println(c); 014 015 //So könnte es der Compiler übersetzen 016 a = "Hallo"; 017 b = "Welt"; 018 c =(new StringBuffer(a)).append(", ").append(b).toString(); 019 System.out.println(c); 020 } 021 } |
Listing1103.java |
Allerdings ist ein Java-Compiler nicht gezwungen, genau so vorzugehen. Die Sprachspezifikation gibt lediglich die Empfehlung, daß es aus Effizienzgründen sinnvoll sein kann, eine solche oder ähnliche Implementierung zu wählen.
Interessanterweise werden durch die Klasse String
keine dynamischen Zeichenketten implementiert. Nach der Initialisierung
eines String
bleiben dessen Länge und Inhalt konstant. Wie ist dann aber die
genaue Arbeitsweise von Funktionen wie substring
oder replace
zu erklären, und was genau passiert bei einer Anweisung wie der
folgenden:
String s = "hello, world";
s = s.substring(0,5);
Die Antwort darauf ist ganz einfach. Die substring-Methode nimmt die Veränderungen nicht auf dem Original-String vor, sondern erzeugt eine Kopie, die mit dem gewünschten Inhalt gefüllt wird. Diese gibt sie dann an den Aufrufer zurück, der das Ergebnis erneut an s zuweist und damit die Originalinstanz für den Garbage Collector freigibt. Durch den Referenzcharakter von Objekten und das automatische Speichermanagement entsteht also der Eindruck, als wären String-Objekte veränderlich.
Als Entwickler braucht man sich hierüber normalerweise keine Gedanken zu machen. Dennoch ist es manchmal nützlich, Zeichenketten zur Verfügung zu haben, die sich dynamisch verändern können (beispielsweise benötigt sie der Compiler selbst zur Implementierung der String-Verkettung). In Java gibt es zu diesem Zweck die Klasse StringBuffer. Sie arbeitet ähnlich wie String, implementiert aber Zeichenketten, die ihre Länge zur Laufzeit ändern können. StringBuffer besitzt nicht so viele Methoden zur Auswertung der Zeichenkette, sondern legt den Schwerpunkt auf Operationen zur Veränderung ihres Inhalts. Die wichtigsten Methoden sollen im folgenden vorgestellt werden.
Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage, Addison Wesley, Version 3.0.1 |
<< | < | > | >> | API | © 1998-2003 Guido Krüger, http://www.javabuch.de |