ejemplo - stringbuffer java example
¿Cuándo se introdujo la optimización Javac StringBuilder/StringBuffer? (4)
Aquí hay una cita de la especificación de idioma de la versión 1 :
Una implementación puede optar por realizar la conversión y la concatenación en un solo paso para evitar crear y luego descartar un objeto
String
intermedio. Para aumentar el rendimiento de la concatenación de cadenas repetidas, un compilador de Java puede usar la claseStringBuffer
(§20.13) o una técnica similar para reducir el número de objetos deString
intermedios que se crean mediante la evaluación de una expresión.
En el momento, tenían StringBuffer
lugar de StringBuilder
.
También una cita de StringBuffer
de JDK1.0.2:
Esta clase es un búfer de crecimiento para los personajes. Se utiliza principalmente para crear cadenas. El compilador lo usa para implementar el operador "+".
Sé que el compilador Javac puede transformar la concatenación de cadenas usando StringBuilder
/ StringBuffer
, y tengo curiosidad por saber a partir de qué versión se introdujo este cambio.
Estoy usando este código de ejemplo:
public class Main {
public static void main(String[] args) {
String a = args[0];
String s = "a";
s = s + a;
s = s + "b";
s = s + "c";
s = s + "d";
s = s + "e";
System.out.println(s);
}
}
Hasta ahora he probado con javac 1.8.0_121
, javac 1.6.0_20
, javac 1.5.0_22
y java 1.4.2_19
.
Aquí hay una muestra del 1.4.2_19
de 1.4.2_19
que veo usando javap -c
de 1.4.2_19
:
6: astore_2
7: new #3; //class StringBuffer
10: dup
11: invokespecial #4; //Method java/lang/StringBuffer."<init>":()V
14: aload_2
15: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
18: aload_1
19: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
22: invokevirtual #6; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
Las 4 versiones parecen estar usando la optimización StringBuilder / StringBuffer, así que tengo curiosidad por saber a partir de qué versión Javac se introdujo este cambio.
He consultado la Especificación del lenguaje Java, Primera edición (desde 1996). No es fácil de encontrar, pero aquí está . El pasaje sobre la optimización de la concatenación estaba allí incluso entonces:
Una implementación puede optar por realizar la conversión y la concatenación en un solo paso para evitar crear y luego descartar un objeto String intermedio. Para aumentar el rendimiento de la concatenación de cadenas repetidas, un compilador de Java puede usar la clase StringBuffer (§20.13) o una técnica similar para reducir el número de objetos de cadena intermedios que se crean mediante la evaluación de una expresión.
La especificación perteneciente a StringBuffer
entonces, pero StringBuilder
(a la que se refiere la redacción actual de JLS) podría considerarse de mejor rendimiento porque sus métodos no están sincronizados.
Esto, sin embargo, no significa que uno deba confiar en la optimización ya que siempre está en su lugar. La concatenación de cadenas en los bucles no se optimizará, por ejemplo.
JLS ya se ha dado en algunas respuestas. Solo quiero señalar que StringBuffer ( https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html ) estuvo allí desde la 1.0, mientras que
StringBuilder ( https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html ) entró en la versión 1.5. Por favor, consulte la sección de since:
de los respectivos javadocs.
Esto no responde a la pregunta , pero quiero simplemente agregar al punto general de que en jdk-9 este StringBuilder::append
es una de las estrategias permitidas , pero no la predeterminada.
private enum Strategy {
/**
* Bytecode generator, calling into {@link java.lang.StringBuilder}.
*/
BC_SB,
/**
* Bytecode generator, calling into {@link java.lang.StringBuilder};
* but trying to estimate the required storage.
*/
BC_SB_SIZED,
/**
* Bytecode generator, calling into {@link java.lang.StringBuilder};
* but computing the required storage exactly.
*/
BC_SB_SIZED_EXACT,
/**
* MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
* This strategy also tries to estimate the required storage.
*/
MH_SB_SIZED,
/**
* MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
* This strategy also estimate the required storage exactly.
*/
MH_SB_SIZED_EXACT,
/**
* MethodHandle-based generator, that constructs its own byte[] array from
* the arguments. It computes the required storage exactly.
*/
MH_INLINE_SIZED_EXACT
}
En realidad, es un invokedynamic
para la concatenación de cadenas, por lo que su implementación ahora es específica de JRE, no del compilador. La estrategia predeterminada por cierto es: MH_INLINE_SIZED_EXACT