Recientemente, cuando estaba buscando trabajo, el examinador me hizo una pregunta simple: "La diferencia entre StringBuffer y StringBuilder, ¿cuáles son sus escenarios de aplicación?" La respuesta del editor se comparte con usted a continuación, para que pueda ser conveniente que todos aprendan en el futuro, a fin de hacer un registro.
De hecho, solo busque el Google Master y tendrá la respuesta: StringBuffer es completamente equivalente a los métodos y funciones en StringBuilder, pero la mayoría de los métodos en StringBuffer usan la palabra clave sincronizada para la modificación, por lo que son seguras de hilo. Sin esta modificación, StringBuilder puede considerarse un hilo inesperado.
Para comprender mejor la respuesta anterior, es mejor ver directamente que la implementación del código fuente de StringBuffer y StringBuilder es más realista. Como programador, "si tiene alguna pregunta, mire el código fuente" es la forma correcta. Puedo decir responsablemente, por supuesto, ¡tienes que tener condiciones!
En la implementación de JDK, tanto StringBuffer como StringBuilder se heredan de AbstractStringBuilder. Para la seguridad y la no seguridad de la múltiples subprocesos, tendrá una comprensión aproximada de los métodos sincronizados en StringBuffer.
Aquí hablaré brevemente sobre el principio de implementación de AbstractStringBuilder: sabemos que usar StringBuffer no es más que mejorar la eficiencia de la conexión de cadena en Java, porque si usa + directamente para la conexión de cadena, JVM creará múltiples objetos de cadena, lo que provocará ciertas sobrecargas. AbstractStringBuilder utiliza una matriz de char para guardar la cadena que debe adjuntar. La matriz Char tiene un tamaño inicial. Cuando la longitud de la cadena de la cadena de apagos excede la capacidad de matriz de char actual, la matriz de char se expande dinámicamente, es decir, volver a aplicar un espacio de memoria más grande y luego copiar la matriz de char actual a una nueva ubicación. Debido a que la sobrecarga de reasignar la memoria y la copia es relativamente grande, cada vez que vuelve a aplicar para el espacio de memoria es de la manera que el espacio de memoria es más grande que la corriente requerida, que es 2 veces.
A continuación, ¡diviértete!
Aquí hay información en Google:
【
StringBuffer comenzó con JDK 1.0
StringBuilder comenzó con JDK 1.5
A partir de JDK 1.5, la operación de conexión (+) con variables de cadena se usa internamente por JVM
Se implementa StringBuilder y esta operación se implementó utilizando StringBuffer.
】
Observamos el proceso de ejecución a través de un programa simple:
Listado 1 buffer.java
Public Class Buffer {public static void main (string [] args) {string s1 = "aaaaa"; Cadena s2 = "bbbbbb"; Cadena r = nulo; int i = 3694; R = S1 + I + S2; para (int j = 0; i <10; j ++) {r+= "23124"; }}}Use el búfer Javap -C de comando para ver su implementación de Bytecode:
Listado de 2 bytecode de clase búfer
Lista 1 y Lista 2 correspondiente, la instrucción LDC en la lista 2 carga la cadena "AAAA" desde el grupo constante hasta la parte superior de la pila, y ISTORE_1 almacena "AAAAA" en la variable 1. Lo siguiente es lo mismo. Sipush empuja un valor constante entero corto (-32768 ~ 32767) a la parte superior de la pila. Aquí está la constante "3694". Para obtener más conjuntos de instrucciones de Java, consulte otro artículo "Conjunto de instrucciones de Java".
Veamos directamente que 13, 13 ~ 17 es nuevo en un objeto StringBuffer y llame a su método de inicialización. 20 ~ 21 es presionar primero la variable 1 en la parte superior de la pila a través de ALOAD_1. Como se mencionó anteriormente, la variable 1 se coloca en la constante de cadena "aaaaaa", y luego llame al método de adición de StringBuffer a través de la instrucción InvokeVirtual para empalmar "aaaaa" juntos. Los siguientes 24 ~ 30 es el mismo. Finalmente, en 33, la función ToString de StringBuffer se llama para obtener el resultado de la cadena y se almacena en la variable 3 a través de la tienda.
Cuando vemos esto, alguien puede decir: "Dado que el JVM usa StringBuffer para conectar cadenas, no necesitamos usar StringBuffer nosotros mismos, solo use"+"¡Justo!" ¿Eso es cierto? Por supuesto que no. Como dice el dicho, "Hay una razón para la existencia", continuemos mirando el bytecode correspondiente al bucle posterior.
37 ~ 42 son todos algunos preparativos antes de ingresar al bucle for. 37, 38 establece J a 1. 44 aquí, IF_ICMPGE compara j con 10. Si J es mayor de 10, saltará directamente a 73, es decir, la declaración de retorno sale de la función; De lo contrario, entra en el bucle, es decir, el bytecode de 47 ~ 66. Aquí solo necesitamos mirar 47 a 51 para saber por qué usamos StringBuffer en nuestro código para manejar las conexiones de cadena, porque cada vez que realizamos la operación "+", JVM tiene que el nuevo objeto StringBuffer para manejar las conexiones de cadena, que será muy costosa cuando hay muchas operaciones de conexión de cadena involucradas.