Warum implementieren StringBuilder und StringBuffer nicht eine gemeinsame Schnittstelle? [geschlossen]

8

Die Unterschiede zwischen StringBuilder und StringBuffer in Java sind gut dokumentiert und wurden in StackOverflow aufgerufen.

Grundsätzlich ist StringBuilder eine nicht synchronisierte Kopie von StringBuffer , mit fast der gleichen Schnittstelle, da es als schneller Ersatz für StringBuffer gedacht war. Ihre API ist praktisch identisch und sie sind tatsächlich Unterklassen der gleichen unzugänglichen abstrakten Klasse im aktuellen JDK.

Ich frage mich daher, warum sie nicht öffentlich verwandt sind. Wenn beide Klassen eine gemeinsame Schnittstelle implementieren oder sogar StringBuffer als Unterklasse von StringBuilder haben, wäre das sinnvoll, da für beide Klassen gemeinsamer Code existiert.

Warum also diese erzwungene Trennung? War es so, dass Programmierer nicht unbeabsichtigt thread-safe mit thread-unsafe-Code mischen? Oder war es nur eine Designaufsicht, die nun bis zum Ende der Ewigkeit vererbt wird?

BEARBEITEN:

Um es klarzustellen: Ich kann spekulieren , warum die Dinge so sind, aber ich hoffe auf konkrete Hinweise auf eine tatsächliche Entscheidung, z. während eines JSR-Prozesses. Alles, was ein Licht auf etwas wirft, was für mich eine Situation ist, die gelegentlich eine gewisse Schwierigkeit verursacht.

EDIT 2:

Die Tatsache, dass beide Klassen Appendable implementiert haben, ist komplett ausgerutscht mein Verstand. Wahrscheinlich, weil diese spezielle Schnittstelle für die meisten Zwecke nutzlos ist - sie kann nur ein einzelnes Zeichen oder ein vorbereitetes Objekt anhängen, und das ist es. In den meisten Fällen ist es nicht sinnvoller als beide Klassen Unterklassen von Object .

EDIT 3:

Nun, hier ist der Grund für genau diese Frage von einer halboffiziellen Quelle :

  

Auswertung durch das Bibliotheksteam:

     

StringBuffer und StringBuilder verwenden standardmäßig keine gemeinsame Verwendung   öffentlicher Supertyp Sie sind nicht als Alternativen gedacht: Eine ist eine   Fehler (StringBuffer), und der andere (StringBuilder) ist es   Ersatz.

     

Es ist klar, dass das Fehlen eines gemeinsamen Supertyps in einigen Fällen die Geschwindigkeit des Internets verlangsamen kann   erhoffte Migration von StringBuffer zu StringBuilder. Die Kehrseite   Wenn wir einen gemeinsamen Supertyp hinzufügen, nehmen wir die Fehler unserer   Vergangenheit und sie in einer öffentlichen Schnittstelle zu verankern, um mit uns für alle zu sein   Zeit. Dies verlangsamt nicht nur die Migration: es entgleist es.

    
thkala 19.03.2012, 03:10
quelle

2 Antworten

3

Ich habe keine JSR-Referenz, aber von meinem exp. unten sind die paar Gründe:

  • StringBuffer als Unterklasse von StringBuilder ist aus Leistungsgründen keine gute Idee . Um StringBuffer threadsicher zu machen, müssen Sie jeden Aufruf in StringBuilder maskieren, was viel Overhead ist.

  • Zusätzlich zum obigen Punkt können Sie weiter optimieren, wenn Sie direkten Zugriff auf die Interna einer Klasse haben , weshalb Java java.lang.concurrent über java.util.Collections.synchronized* apis hinzugefügt hat. Da direkter Zugriff mehr Optionen für die Optimierung gibt. Um diesen Punkt zu unterstützen Referenz aus dem IBM Blog

  • Ich füge zum ersten Punkt hinzu, ich nicht denke, dass dies eine Design-Übersicht ist, da beide Klassen final sind, also definitiv nicht wollen, dass diese Klassen unterklassifiziert werden.

  • Bei den gleichen Schnittstellen implementieren beide Klassen die gleichen Schnittstellen, d. h. Serializable, Appendable, CharSequence . So sind sie Drop-In-Ersatz. Die einzige Sache ist, dass sie nicht eine gemeinsame Schnittstelle, sondern drei gemeinsame Schnittstellen implementieren. Das macht Sinn, da es keine Notwendigkeit gibt, eine aufgeblähte Schnittstelle zu haben, die technisch die Summe der aktuellen Schnittstellen ist ( Serializable, Appendable, CharSequence ).

BEARBEITEN:

  • Zu @MatthewFlaschen Punkt, dass es apis gibt, die gleiche s / w StringBuffer und StringBuilder sind, aber nicht in irgendeiner der implementierten Schnittstellen. Dies hat mehr mit Rückwärtskompatibilität zu tun. Sie möchten eine neue API hinzufügen, aber die Schnittstelle wird von vielen anderen Klassen verwendet, so dass das Ändern einer Schnittstelle möglicherweise nicht möglich ist. Das ist eine gut durchdachte Entscheidung, die Java-Leute getroffen haben könnten. Also werde ich nicht sagen, dass es ein Fehler ist.

EDIT 2:

SEITENHINWEIS: Eine weitere zu beachtende Sache ist, dass StringBuffer in 1.0 eingeführt wurde und StringBuilder in 1.5. Also werden die Apis, die es in beiden Klassen gibt, aber nicht in Interfaces, später eingeführt und nicht zum Zeitpunkt der Erstellung dieser Klassen.

    
havexz 19.03.2012, 03:39
quelle
2

Sie implementieren beide tatsächlich Appendable .

Ich stimme nicht zu, dass dies nutzlos ist. Meiner Erfahrung nach hat ein großer Teil der Verwendung von StringBuilder / StringBuffer nur mit Strings zu tun (die CharSequence implementieren). Für den Rest können Sie String.valueOf aufrufen, bevor Sie es übergeben.

Es wäre praktisch, wenn es eine andere Schnittstelle gäbe, die auch die anderen Methoden wie append(long) hätte. Aber das ist nicht wichtig.

Es wäre vernünftig, eine gemeinsame Schnittstelle zu haben. Sie haben unterschiedliche Leistungs- und Threading-Eigenschaften, aber das ist gut und richtig für viele Schnittstellen im JDK.

Beispiel: CopyOnWriteArrayList in einem Array -basierte threadsichere Liste (erstellt für jeden Schreibvorgang eine neue Liste), während LinkedList ist eine nicht threadsichere verknüpfte Liste.

    
Matthew Flaschen 19.03.2012 03:14
quelle