Descripción general
StringBuilder y StringBuffer son dos conceptos fácilmente confusos. Este artículo comienza desde el código fuente y simplemente analiza las similitudes y diferencias entre los dos.
Es fácil saber que uno de estos dos es seguro de hilo, y el de hilo seguro es ineficiente.
Descripción en Java Doc
Java Doc es una anotación escrita por personas que escriben el código fuente. Veamos primero a Java Doc.
StringBuilder
Una secuencia mutable de caracteres. Esta clase proporciona una API compatible con StringBuffer, pero sin garantía de sincronización. Esta clase está diseñada para su uso como reemplazo de StringBuffer en lugares donde el búfer de cadena estaba siendo utilizada por un solo hilo (como es generalmente el caso). Siempre que sea posible, se recomienda que esta clase se use con preferencia a StringBuffer, ya que será más rápido en la mayoría de las implementaciones.
Las operaciones principales en un StringBuilder son los métodos de admitir e insertar, que están sobrecargados para aceptar datos de cualquier tipo. Cada uno convierte efectivamente un dato dado en una cadena y luego agrega o inserta los caracteres de esa cadena en el constructor de cadenas. El método Append siempre agrega estos caracteres al final del constructor; El método de inserción agrega los caracteres en un punto especificado.
Por ejemplo, si Z se refiere a un objeto String Builder cuyo contenido actual es "Inicio", entonces la llamada del método Z.append ("le") haría que el constructor de cadenas contenga "sobresalto", mientras que Z.insert (4, "le") alteraría el constructor de cadenas para contener "estrella".
En general, si SB hace referencia a una instancia de un StringBuilder, entonces SB.Append (x) tiene el mismo efecto que SB.INSERT (SB.Length (), X).
Cada constructor de cadenas tiene una capacidad. Mientras la longitud de la secuencia de caracteres contenida en el constructor de cadenas no exceda la capacidad, no es necesario asignar un nuevo búfer interno. Si el búfer interno se desborda, se hace automáticamente más grande.
Las instancias de StringBuilder no son seguras para su uso mediante múltiples hilos. Si se requiere dicha sincronización, se recomienda utilizar que se use java.lang.stringbuffer.
A menos que se indique lo contrario, transmitir un argumento nulo a un constructor o método en esta clase hará que se arroje una NullPointerException.
Desde:
1.5
Autor:
Michael McCloskey
Ver también:
java.lang.stringbuffer
java.lang.string
Stringbuffer
Una secuencia de caracteres mutable segura de hilo. Un búfer de cadena es como una cadena, pero se puede modificar. En cualquier momento, contiene alguna secuencia particular de caracteres, pero la longitud y el contenido de la secuencia se pueden cambiar a través de ciertas llamadas de método.
Los búferes de cadena son seguros para su uso mediante múltiples hilos. Los métodos se sincronizan cuando sea necesario para que todas las operaciones en cualquier instancia particular se comporten como si ocurran en algún orden en serie que sea consistente con el orden de las llamadas de método realizadas por cada uno de los hilos individuales involucrados.
Las operaciones principales en un StringBuffer son los métodos de adición e inserción, que se sobrecargan para aceptar datos de cualquier tipo. Cada uno convierte efectivamente un dato dado en una cadena y luego agrega o inserta los caracteres de esa cadena en el búfer de cadena. El método de agregado siempre agrega estos caracteres al final del búfer; El método de inserción agrega los caracteres en un punto especificado.
Por ejemplo, si Z se refiere a un objeto de búfer de cadena cuyo contenido actual es "inicio", entonces el método llama z.append ("le") haría que el búfer de cadena contenga "sobresalto", mientras que z.insert (4, "le") alteraría el búfer de cadena para contener "estrella".
En general, si SB hace referencia a una instancia de un stringbuffer, entonces sb.append (x) tiene el mismo efecto que sb.insert (sb.length (),
Cada vez que se produce una operación que involucra una secuencia de origen (como agregar o insertar desde una secuencia de origen), esta clase se sincroniza solo en el búfer de cadena que realiza la operación, no en la fuente. Tenga en cuenta que si bien StringBuffer está diseñado para ser seguro para usar simultáneamente desde múltiples subprocesos, si el constructor o la operación de append o inserción se pasa una secuencia de origen que se comparte entre los subprocesos, el código de llamado debe garantizar que la operación tenga una vista consistente e inmutable de la secuencia de origen para la duración de la operación. Esto podría satisfacerse con la persona que llamó un bloqueo durante la llamada de la operación, utilizando una secuencia de origen inmutable o no compartiendo la secuencia de origen a través de los hilos.
Cada búfer de cadena tiene una capacidad. Mientras la longitud de la secuencia de caracteres contenida en el búfer de cadena no exceda la capacidad, no es necesario asignar una nueva matriz de búfer interno. Si el búfer interno se desborda, se hace automáticamente más grande.
A menos que se indique lo contrario, transmitir un argumento nulo a un constructor o método en esta clase hará que se arroje una NullPointerException.
A partir del lanzamiento JDK 5, esta clase se ha complementado con una clase equivalente diseñada para usar por un solo hilo, StringBuilder. La clase StringBuilder generalmente debe usarse con preferencia a esta, ya que admite todas las mismas operaciones, pero es más rápido, ya que no funciona sincronización.
Desde:
JDK1.0
Autor:
Arthur Van Hoff
Ver también:
java.lang.stringbuilder
java.lang.string
Resumen de Javadoc
De lo anterior, podemos ver:
Tanto StringBuffer como StringBuilder pueden considerarse cadenas variables.
StringBuffer es seguro de hilo y aparece primero, y está disponible en JDK1.0.
StringBuilder no es seguro y aparece más tarde y solo existe en JDK1.5.
Las interfaces de los dos son exactamente las mismas, y StringBuilder es más rápido.
De hecho, es bueno usarlo normalmente, solo conozca estos puntos, pero aún quiero ver cómo se implementa en el código fuente.
Código fuente
Cómo lograr la seguridad del hilo
Puede ver en el código fuente que heredan una clase abstracta AbstractStringBuilder
CLASE FINAL Public StringBuffer extiende AbstractStringBuilder implementos java.io.serializables, CharSECECEPublic de clase final StringBuilder extiende AbstractStringBuilder implementa java.io.serializable, CharSequence
La cantidad de código no es muy grande, líneas de código StringBuilder440, líneas de código StringBuffer718, y la mayoría es AbstractStringBuilder, con un total de 1440 líneas de código.
Desde varias perspectivas, observamos el código, uno es cómo se ven algunas estructuras internas clave, y la otra es cómo se implementan las funciones que comúnmente usamos. Debido a que la cadena es inmutable, se coloca en una piscina constante. Se adivina que StringBuilder y StringBuffer deben implementarse utilizando una matriz de char.
/*** El valor se utiliza para el almacenamiento de personajes. */ char [] valor; /*** El recuento es el número de caracteres utilizados. */ int count;
Se puede ver que los datos se almacenan con valor y la longitud está representada por un recuento.
Veamos las diferentes implementaciones de varios métodos comunes.
Stringbuffer
@Override public SynCronized StringBuffer append (String Str) {toStringCache = null; super.append (str); devolver esto; } / ** * @throws stringInDexutefBoundSexception {@inheritdoc} * / @Override public SynCronized StringBuffer Insert (int offset, String Str) {toStringCache = null; super.insert (offset, str); devolver esto; } @Override public sincronized String toString () {if (toStringCache == null) {toStringCache = arrays.copyOfRange (valor, 0, count); } return new String (toStringCache, true); }StringBuilder
@Override public StringBuilder append (string str) {super.append (str); devolver esto; } / ** * @throws stringInDexutefBoundSexception {@inheritdoc} * / @Override public StringBuilder Insert (int offset, String Str) {super.insert (offset, str); devolver esto; } @Override public String toString () {// Crear una copia, no comparta la matriz devuelve nueva cadena (valor, 0, recuento); }Como se puede ver en el código, en la mayoría de los casos, Strinbbuffer solo agrega una palabra clave sincronizada para garantizar la seguridad de los subprocesos. Pero el método de tostración es diferente, por lo que hablaré de esto más adelante.
Inicializar el tamaño y cómo crecer
Dado que en realidad es una matriz, el tamaño y el método de crecimiento de la matriz que comienza desde el que comienza es muy importante. Echemos un vistazo a través del código.
/** * Construye un búfer de cadena sin caracteres y una * capacidad inicial de 16 caracteres. */ public stringBuffer () {super (16); } /** * Construye un constructor de cadenas sin caracteres y una * capacidad inicial de 16 caracteres. */ public stringBuilder () {super (16); }Como puede ver, ambos constructores predeterminados indican que el tamaño de matriz predeterminado es 16.
¿Por qué 16? No entendí.
¿Qué se preocupa por cómo crecer? Echemos un vistazo a la implementación de Append
public AbstractStringBuilder append (String Str) {if (str == null) return appendNull (); int len = str.length (); EnsurecapacityInternal (recuento + len); str.getChars (0, len, valor, recuento); recuento += len; devolver esto; } /** * Este método tiene el mismo contrato que Ensurecapacidad, pero * nunca está sincronizado. */ private void setureCapacityInternal (int mínimocapacity) {// Código consciente de desbordamiento if (MinimumCapacity - Value.length> 0) ExpandCapacity (MinimumCapacity); } /** * Esto implementa la semántica de expansión de Ensurecapacidad sin * Verificación de tamaño o sincronización. */ void expandCapacity (int minmumCapacity) {int newCapacity = value.length * 2 + 2; if (newCapacity - MinimumCapacity <0) NewCapacity = MinimumCapacity; if (newCapacity <0) {if (mínimo de capacidad <0) // desbordamiento tirar nueva outOfMemoryError (); newCapacity = Integer.max_value; } value = arrays.copyOf (valor, newcapacity); }Los tres métodos anteriores explican cómo expandir la capacidad.
Pon la capacidad actual *2+2
Si la longitud recién agregada es mayor que este valor, establezca en el valor recién agregado
Si se desbordan, tire deMemoryError
Implementación de ToString en StringBuffer
/*** Un caché del último valor devuelto por ToString. Bordeado * Siempre que se modifique StringBuffer. */ Private Transient Char [] ToStringCache; @Override public SynCronized StringBuffer append (String Str) {toStringCache = null; super.append (str); devolver esto; } @Override public sincronized String toString () {if (toStringCache == null) {toStringCache = arrays.copyOfRange (valor, 0, count); } return new String (toStringCache, true); }Como puede ver, se define una matriz ToStringCache. Cada vez que los datos cambian, esto se establece en NULL. Cuando ToString, tómelo nuevamente de los datos actuales.
La palabra clave transitoria es evitar que esta matriz sea serializada.
resumen
De hecho, el código fuente de Java en sí es relativamente simple. Si puede comenzar con el código fuente, puede comprender muchos principios más profundamente. Este artículo simplemente enumera algunos códigos fuente y explica brevemente las similitudes y diferencias entre StringBuffer y StringBuilder. Los amigos interesados pueden echarle un vistazo ellos mismos.
El artículo anterior analiza brevemente las similitudes y diferencias entre StringBuilder y StringBuffer desde la perspectiva del código fuente (análisis integral) es todo el contenido que comparto con usted. Espero que pueda darle una referencia y espero que pueda apoyar más a Wulin.com.