Recientemente estoy estudiando String. Tengo curiosidad sobre el proceso de concatenación de cadenas. Bienvenidos a discutirlo juntos. . .
Fragmento 1
Prueba de clase pública { public static void main (String args []) { String str = "hello " + "world " ; } }
Ver estructura de archivos de clase con javap
Desde la estructura del archivo, podemos ver que "hola" + "mundo" se compila directamente en "helloworld", y esta constante se carga en la pila de operandos, y luego se almacena en la tabla de variables locales, y finalmente finaliza la devolución.
Prueba de clase pública { public static void main (String args []) { String str1 = "hello " + "world " ; String str2 = "helloworld ;
System.out.print (str.equals (str));
}
}
Por lo tanto, el código anterior se ejecuta igual y el resultado es verdadero: String str = "hello" + "world" y String str = "helloworld" tienen el mismo efecto.
Fragmento 2
Prueba de clase pública { public static void main (String args []) { String str = new String ( "helloworld " ); } }
Ver estructura de archivos de clase con javap
Desde la estructura del archivo, podemos ver que antes que nada una nueva Cadena, copie el valor superior de la pila y empuje el valor copiado en la parte superior de la pila, luego almacénelo en la tabla de variables locales y finalmente regrese.
Fragmento 3
Después de comprender el proceso anterior, comenzamos a entrar en el tema.
Prueba de clase pública { public static void main (String args []) { String str = " hello " ; str = str + " mundo " ; } }
¿Qué pasa con el código anterior?
Veamos primero el archivo de clase
Primero almacene la variable str en la tabla de variables locales, luego nuevo StringBuilder (), e inicialícelo, luego llame al método StringBuilder.append () para unir las cadenas, y luego llame a nuevo String () a través de StringBuilder.toString () para obtener una nueva variable de cadena , Y luego almacene esta variable en la tabla de variables locales, y finalmente devuelva los extremos.
Entonces, el proceso del fragmento de código 3 es en realidad nuevo StringBuilder (). Append (str) .append ("world"). ToString ().
Dado que el proceso de unión de String con signo más utiliza los métodos append y toString de StringBuilder, es mejor observar el proceso de estos dos métodos.
// StringBuilder append method public StringBuilder append (String str) { // Llama a la clase padre AbstractStringBuilder append method super .append (str); devuelve esto ; } public AbstractStringBuilder append (String str) { // Si la cadena está vacía, Devuelve "null" if (str == null ) return appendNull (); int len = str.length (); // Obtenga el tamaño de la matriz, si el tamaño de la nueva cadena es mayor que la longitud de char [], entonces una nueva char [], y asigne el char original al nuevo char [] allowCapacityInternal (count + len); //Ponga str en char [], la capa inferior llama al método local System.arraycopy str.getChars (0 , len, value, count); count + = len; return this ; } // Obtenga el tamaño del contenedor private int newCapacity ( int minCapacity) { // Si el tamaño de la nueva cadena + cadena existente es mayor que el tamaño de char [], el tamaño del nuevo contenedor se duplica +2 int newCapacity = (value.length << 1) + 2 ; if (newCapacity-minCapacity < 0 ) { newCapacity = minCapacity; } //Si newCapacity <Integer.MAX_VALUE-8, entonces el tamaño de char [] se toma de newCapacity; si Integer.MAX_VALUE-8 <newCapacity <Integer.MAX_VALUE, entonces el tamaño de char [] se toma de Integer.MAX_VALUE; si newCapacity> Integer.MAX_VALUE. return (newCapacity <= 0 || MAX_ARRAY_SIZE-newCapacity <0)? hugeCapacity (minCapacity): newCapacity; }
// 而 StringBuilder 的 toString () 调用 的 是 new String () public String toString () { return new String (valor, 0 , cuenta); }} Cadena pública ( valor de char [], int offset, int count) { if (offset <0 ) { throw new StringIndexOutOfBoundsException (offset); } if (recuento <= 0 ) { if (recuento <0 ) { arrojar una nueva StringIndexOutOfBoundsException (recuento); } if (desplazamiento <=value.length) { this .value = "" .value; return ; } } if (offset> value.length- count) { throw new StringIndexOutOfBoundsException (offset + count); } // según la longitud de la cadena después de empalmar Nuevo char [], y copie el valor de la matriz char [] original en el nuevo char [], ahorrando memoria esto .value = Arrays.copyOfRange (value, offset, offset + count); } }
Se puede ver en el código anterior: un pequeño proceso de empalme "+" utilizó System.arraycopy tres veces para copiar la matriz anterior a la nueva matriz.
)