Hola de nuevo Como ya escribimos, la próxima semana comenzará un nuevo grupo de capacitación en el curso
"Desarrollador Java" , de acuerdo con la tradición establecida, compartiremos con ustedes la traducción de material interesante sobre el tema.
Comenzando con JDK 9, la concatenación de cadenas ha experimentado cambios significativos.JEP 280 ("Indicar concatenación de cadenas") se implementó como parte de
JDK 9 y, de acuerdo con la sección Resumen: "Cambia la secuencia de bytecode de concatenación de cadenas generada por
javac para usar llamadas
dinámicas invocadas a las funciones de la biblioteca JDK". El efecto que esto tiene en la concatenación de cadenas en Java se nota más fácilmente al observar la salida de Java de las clases que usan la concatenación de cadenas que se compilaron en JDK antes de JDK 9 y después de JDK 9.

Para la primera demostración, se utilizará una clase simple de Java llamada "HelloWorldStringConcat".
package dustin.examples; import static java.lang.System.out; public class HelloWorldStringConcat { public static void main(final String[] arguments) { out.println("Hello, " + arguments[0]); } }
La siguiente es una comparación de las diferencias para la salida -verbose javap para el método
main(String)
de la clase HelloWorldStringConcat cuando se compila con JDK 8
(AdoptOpenJDK) y JDK 11
(Oracle OpenJDK) . Destaqué algunas diferencias clave.
Salida javap JDK 8 Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcat.class Last modified Jan 28, 2019; size 625 bytes MD5 checksum 3e270bafc795b47dbc2d42a41c8956af Compiled from "HelloWorldStringConcat.java" public class dustin.examples.HelloWorldStringConcat minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
Salida javap JDK 11 Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcat.class Last modified Jan 28, 2019; size 908 bytes MD5 checksum 0e20fe09f6967ba96124abca10d3e36d Compiled from "HelloWorldStringConcat.java" public class dustin.examples.HelloWorldStringConcat minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: getstatic #2
La sección "Descripción" en
JEP 280 describe esta diferencia: "La idea es reemplazar todo el baile de unión StringBuilder con una simple llamada
invokedynamic
a
java.lang.invoke.StringConcatFactory , que tomará valores que deben fusionarse". La misma sección muestra una comparación similar de la salida compilada para un ejemplo de concatenación de cadenas similar.
La salida compilada con JDK 11 para una concatenación fácil no es solo menos líneas que la salida de JDK 8; él también tiene menos operaciones "caras". Se pueden lograr mejoras de rendimiento potenciales debido al hecho de que no es necesario ajustar tipos primitivos y no es necesario crear muchos objetos adicionales. Uno de los motivos principales de este cambio fue "sentar las bases para crear controladores de concatenación de cadenas optimizados que se implementen sin la necesidad de cambiar el compilador de código de bytes a Java" y "habilitar futuras optimizaciones de concatenación de cadenas sin cambios adicionales en el código de bytes generado por javac. "
Hay una consecuencia interesante de esto en términos del uso de
StringBuffer (que de todos modos me
resulta difícil encontrar un buen uso ) y
StringBuilder . En JEP 280 en "No objetivo", se dijo que no "introduciría ninguna API nueva para String y / o StringBuilder que pudiera ayudar a crear estrategias de traducción más eficientes". En este sentido, para la concatenación de cadenas simple, como en el ejemplo al principio de esta publicación, el uso explícito de StringBuilder y StringBuffer prácticamente excluye al compilador del uso de la característica introducida en
JEP 280 , que discutimos en esta publicación.
Los siguientes dos listados muestran implementaciones similares de la aplicación simple que se muestra arriba, pero en lugar de concatenar cadenas, usan StringBuilder y StringBuffer respectivamente. Cuando se ejecuta javap -verbose para estas clases después de que se compilan con JDK 8 y con JDK 11, no hay diferencias significativas en los métodos principales (String []).
El uso explícito de StringBuilder en JDK 8 y JDK 11 es el mismo package dustin.examples; import static java.lang.System.out; public class HelloWorldStringBuilder { public static void main(final String[] arguments) { out.println(new StringBuilder().append("Hello, ").append(arguments[0]).toString()); } }
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuilder.class Last modified Jan 28, 2019; size 627 bytes MD5 checksum e7acc3bf0ff5220ba5142aed7a34070f Compiled from "HelloWorldStringBuilder.java" public class dustin.examples.HelloWorldStringBuilder minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuilder.class Last modified Jan 28, 2019; size 627 bytes MD5 checksum d04ee3735ce98eb6237885fac86620b4 Compiled from "HelloWorldStringBuilder.java" public class dustin.examples.HelloWorldStringBuilder minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
El uso explícito de StringBuffer en JDK 8 y JDK 11 es el mismo package dustin.examples; import static java.lang.System.out; public class HelloWorldStringBuffer { public static void main(final String[] arguments) { out.println(new StringBuffer().append("Hello, ").append(arguments[0]).toString()); } }
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuffer.class Last modified Jan 28, 2019; size 623 bytes MD5 checksum fdfb90497db6a3494289f2866b9a3a8b Compiled from "HelloWorldStringBuffer.java" public class dustin.examples.HelloWorldStringBuffer minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuffer.class Last modified Jan 28, 2019; size 623 bytes MD5 checksum e4a83b6bb799fd5478a65bc43e9af437 Compiled from "HelloWorldStringBuffer.java" public class dustin.examples.HelloWorldStringBuffer minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
JDK 8 y JDK 11 Manejo de concatenaciones de cadenas en buclePara el último ejemplo de cambios en JEP 280 en acción, uso un código de muestra que puede romper la susceptibilidad de algunos desarrolladores de Java y concatenar cadenas en un bucle. Tenga en cuenta que este es solo un ejemplo ilustrativo y que todo estará bien, pero no intente repetirlo en casa.
package dustin.examples; import static java.lang.System.out; public class HelloWorldStringConcatComplex { public static void main(final String[] arguments) { String message = "Hello"; for (int i=0; i<25; i++) { message += i; } out.println(message); } }
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcatComplex.class Last modified Jan 30, 2019; size 766 bytes MD5 checksum 772c4a283c812d49451b5b756aef55f1 Compiled from "HelloWorldStringConcatComplex.java" public class dustin.examples.HelloWorldStringConcatComplex minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: ldc #2
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcatComplex.class Last modified Jan 30, 2019; size 1018 bytes MD5 checksum 967fef3e7625965ef060a831edb2a874 Compiled from "HelloWorldStringConcatComplex.java" public class dustin.examples.HelloWorldStringConcatComplex minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: ldc #2
En la presentación
"Suficiente java.lang.String to Hang Ourselves ..." , el Dr.
Heinz M. Kabutz y
Dmitry Vyazelenko discuten los cambios realizados en la concatenación de cadenas Java y los resumen brevemente, "+ más no compilado en StringBuilder ". En la diapositiva Lecciones del día de hoy, dicen: "Use + en lugar de StringBuilder donde sea posible" y "Recompile clases para Java 9+".
Los cambios implementados en JDK 9 con
JEP 280 , "permitirán en el futuro optimizar la concatenación de cadenas, sin requerir cambios adicionales en el bytecode generado por javac". Curiosamente, se anunció recientemente que JEP 348 ("Java Compiler Intrinsics for JDK APIs") ahora es un candidato para JEP, y su objetivo es utilizar un enfoque similar para compilar los métodos
String :: format y
Objects::hash
.
¿Cuál crees que es un artículo útil? Estamos a la espera de sus comentarios e invitamos a todos a una
jornada de puertas abiertas en el curso Java Developer, que se llevará a cabo el 25 de marzo por el director general de OTUS -
Vitaly Chibrikov .