2012-03-19 8 views
8

Las diferencias entre StringBuilder y StringBuffer en Java están bien documentadas y han sido touched upon in StackOverflow también.¿Por qué no tener StringBuilder y StringBuffer implementando una interfaz común?

Básicamente, StringBuilder es una copia no sincronizada de StringBuffer, con prácticamente la misma interfaz, ya que fue pensada como un reemplazo directo más rápido para StringBuffer. Su API es prácticamente idéntica y en realidad son subclases de la misma clase abstracta inaccesible en el JDK actual.

Lo único que me pregunto, por lo tanto, es por qué no están públicamente relacionados. Tener ambas clases implementando una interfaz común o incluso teniendo StringBuffer como una subclase de StringBuilder tendría sentido, permitiendo la existencia de código compartido para ambas clases.

¿Por qué esta separación forzada? ¿Era para que los programadores no mezclaran inadvertidamente thread-safe con código inseguro? ¿O fue solo un control de diseño que ahora será heredado hasta el final de la eternidad?

EDIT:

Para aclarar las cosas: puedo especular sobre por qué las cosas son así, pero estoy con la esperanza de referencias concretas a una decisión real, por ejemplo, durante un proceso de JSR. Cualquier cosa que arroje algo de luz sobre lo que, para mí, es una situación que ocasiona cierta cantidad de dificultad ocasionalmente.

EDIT 2:

El hecho de que ambas clases implementan Appendable deslizó por completo mi mente. Probablemente porque esa interfaz en particular es inútil para la mayoría de los propósitos: solo puede agregar un solo carácter o un objeto preparado y eso es todo. En la mayoría de los casos, no es más útil que ambas clases son subclases de Object.

Datos 3:

Bueno, aquí es la razón de ser exactamente esta pregunta desde a semi-official source:

Evaluación por el equipo de bibliotecas:

Es por diseño que StringBuffer y StringBuilder no comparte ningún supertipo público común. No están destinados a ser alternativas: uno es un error (StringBuffer), y el otro (StringBuilder) es su reemplazo .

Claramente, la falta de un supertipo común puede, en algunos casos, ralentizar la migración esperada de StringBuffer a StringBuilder. La otra cara de la moneda es que al agregar un supertipo común, estaríamos tomando los errores de nuestro pasado y consagrándolos en una interfaz pública para estar con nosotros durante todo el tiempo . Esto no solo ralentiza la migración: lo descarrila.

Respuesta

3

No tengo una referencia JSR pero de mi exp. a continuación son las pocas razones:

  • StringBuffer como una subclase deStringBuilderno es una buena idea por razones de rendimiento. En cuanto a hacer seguro el subproceso StringBuffer, debe enmascarar cada llamada al StringBuilder, que es una gran sobrecarga.

  • Agregando a punto por encima, se puede optimizar aún más, si tiene acceso directo sobre el funcionamiento interno de una clase que es la razón por la Java añadió java.lang.concurrent sobre java.util.Collections.synchronized* apis. A medida que un acceso más directo brinda más opciones para la optimización. Para el apoyo de este punto Reference from the IBM blog

  • Además de añadir al primer punto, No creo que esto es un descuido de diseño ya que tanto las clases son final por lo que definitivamente no quiero que estas clases para tener subclases.

  • En cuanto a las mismas interfaces, ambas clases implementan las mismas interfaces, es decir, Serializable, Appendable, CharSequence. Entonces son reemplazos directos. Lo único es que no implementan una interfaz común sino tres interfaces comunes. Lo cual tiene sentido, ya que no es necesario tener una interfaz inflada que técnicamente va a ser la suma de las interfaces actuales (Serializable, Appendable, CharSequence).

EDIT:

  • Para @MatthewFlaschen punto, que hay apis que son mismo b/w StringBuffer y StringBuilder pero no en cualquiera de las interfaces implementadas. Esto tiene más que ver con la compatibilidad con versiones anteriores. Desea agregar una nueva API pero la interfaz está siendo utilizada por muchas otras clases, por lo que cambiar una interfaz puede no ser una solución viable. Esa es una decisión bien pensada que los chicos de Java podrían haber tomado. Así que no diré que es un error.

EDIT 2:

SIDE NOTA: Otra cosa a destacar es que StringBuffer se introdujo en 1,0 y StringBuilder en 1.5. Entonces las apis que están en ambas clases pero no en interfaces se presentan más adelante y no al momento de crear estas también clases.

+0

Existen métodos, p. append (long) que están en ambas clases pero ninguna de las interfaces. –

+0

Aunque creo que como Vector y ArrayList extienden AbstractList, StringBuffer y StringBuilder podrían haber extendido una clase abstracta similar. No he buscado la última fuente, pero StringBuilder parecía ser una estafa directa de StringBuffer menos la sincronización. –

+0

@MatthewFlaschen append() es de Appendable. –

2

En realidad ambos implementan Appendable.

No estoy de acuerdo en que esto sea inútil.En mi experiencia, una gran parte del uso de StringBuilder/StringBuffer solo trata con cadenas (que implementan CharSequence). Para el resto, puede llamar al String.valueOf antes de pasarlo.

Sería conveniente si hubiera otra interfaz que también tuviera los otros métodos, como append(long). Pero eso no es esencial.

Sería razonable tener una interfaz común. Tienen diferentes características de rendimiento y subprocesamiento, pero eso es correcto y cierto para muchas interfaces en el JDK.

Por ejemplo, CopyOnWriteArrayList en una lista de temas de seguridad basada en matrices (hace una nueva lista para cada escritura), mientras que LinkedList es una lista enlazada no thread-safe.

+0

No respondió la pregunta, ni siquiera dio una idea de por qué podría ser así. – FriendlyGuy

+0

@MackieChan, no estoy de acuerdo. Dije: "Sería razonable tener una interfaz común", que es otra forma de decir: "Sí, es un control de diseño". –

+0

Honestamente, Appendable se me olvidó, sobre todo porque regularmente añado números e.t.c. en mi código Realmente no encuentro esa interfaz en particular muy útil, porque te obliga a convertir todo en una cadena de antemano. Sin mencionar que el contenido existente es inmutable ... – thkala

Cuestiones relacionadas