90 nuevas características (y API) en JDK 11

Hola Habr! Le presento la traducción del artículo " 90 Nuevas características (y API) en JDK 11 " de Simon Ritter.



Para muchos, el nuevo ciclo de lanzamiento de JDK de seis meses significa que algunos ni siquiera han descubierto qué nuevas características hay en JDK 10, y JDK 11 está a punto. logró encontrarse en JDK 10. Por lo tanto, para JDK 11 se decidió hacer lo mismo. Sin embargo, se eligió un formato diferente. Esta publicación se dividirá en dos secciones: nuevas funciones que están disponibles para los desarrolladores (API pública) y todo lo demás. Por lo tanto, si solo está interesado en lo que afecta directamente su desarrollo, puede omitir la segunda parte.


El número total de cambios que podrían calcularse resultó ser 90 (esto es JEP más nuevas clases y métodos, excluyendo métodos separados para el cliente HTTP y Flight Recorder ) ( nota del traductor: Java Flight Recorder (JFR) fue uno de los comerciales integrados de Oracle en el JDK, pero a partir de Java 11, gracias a JEP 328 , se transfirió a código abierto) . Aunque JDK 11 logró encontrar once cambios menos que en JDK 10, creo que es justo decir que se ha agregado más funcionalidad a JDK 11, definitivamente en el nivel de JVM.


Nuevas características notables para el desarrollador


JDK 11 tiene bastantes cambios que podrían afectar el estilo de desarrollo. Hay un ligero cambio de sintaxis, muchas API nuevas y la capacidad de ejecutar aplicaciones en un solo archivo sin usar un compilador ( traductor de notas: los llamados archivos shebang ). Además, el gran cambio (y el último ) es la eliminación del módulo de agregación java.se.ee , que puede afectar la migración de una aplicación existente a JDK 11.


JEP 323: sintaxis de variable local para parámetros de Lambda


En JDK 10, se introdujo la inferencia de variable local (o inferencia de tipo) ( JEP 286 ). Esto simplifica el código porque ya no necesita especificar explícitamente el tipo de la variable local, puede usar var en su lugar. JEP 323 extiende el uso de esta sintaxis, que ahora también es aplicable a los parámetros de las expresiones lambda. Un simple ejemplo:


list.stream() .map((var s) -> s.toLowerCase()) .collect(Collectors.toList()); 

Un programador de Java atento indicaría que las expresiones lambda ya tienen inferencia de tipo, por lo que usar var sería (en este caso) redundante. Podríamos escribir con la misma facilidad el mismo código que:


  list.stream() .map(s -> s.toLowerCase()) .collect(Collectors.toList()); 

¿Por qué agregar soporte var? La respuesta es un caso especial: cuando desea agregar una anotación a un parámetro lambda. Esto no puede hacerse sin ningún tipo de participación. Para evitar el uso de un tipo explícito, podemos usar var para simplificar las cosas, de esta manera:


  list.stream() .map((@Notnull var s) -> s.toLowerCase()) .collect(Collectors.toList()); 

Este cambio requirió cambios en la Especificación del lenguaje Java (JLS) , en particular:


Página 24: La descripción del identificador especial var.
Página 627-630: parámetros de Lambda
Página 636: Evaluación en tiempo de ejecución de expresiones Lambda
Página 746: sintaxis Lambda


JEP 330: Lanzar programas de código fuente de un solo archivo


Una de las críticas de Java es la redundancia de la sintaxis, y la "ceremonia" asociada con el lanzamiento de incluso una aplicación trivial puede aumentar seriamente el umbral de entrada para un principiante. Para escribir una aplicación que simplemente imprima "¡Hola Mundo!", Debe escribir una clase con el método principal de vacío público estático y usar el método System.out.println (). Una vez hecho esto, debe compilar el código usando javac. Finalmente, puede iniciar una aplicación que dará la bienvenida al mundo. Ejecutar el mismo script en la mayoría de los idiomas modernos es mucho más simple y rápido.


JEP 330 elimina la necesidad de compilar una aplicación de un solo archivo. Ahora solo ingrese:


  java HelloWorld.java 

El iniciador de Java identifica que el archivo contiene el código fuente de Java y compila el código en un archivo * .class antes de ejecutarlo.


Los argumentos colocados después del nombre del archivo fuente se pasan como argumentos cuando se inicia la aplicación. Los argumentos colocados antes del nombre del archivo fuente se pasan como argumentos al iniciador de Java después de compilar el código (esto le permite configurar cosas como classpath en la línea de comando). Los argumentos relacionados con el compilador (por ejemplo, classpath) también se pasarán a javac para su compilación.


Un ejemplo:


  java -classpath /home/foo/java Hello.java Bonjour 

Será equivalente a:


  javac -classpath /home/foo/java Hello.java java -classpath /home/foo/java Hello Bonjour 

Este JEP también proporciona soporte para archivos shebang. Para reducir la necesidad de mencionar incluso el iniciador de Java en la línea de comando, puede incluirlo en la primera línea del archivo fuente. Por ejemplo:


  #!/usr/bin/java --source 11 public class HelloWorld { ... 

Se requiere el indicador -source con la versión de Java utilizada.


JEP 321: Cliente HTTP (estándar)


JDK 9 introdujo una nueva API para admitir el protocolo de Cliente HTTP ( JEP 110 ). Como JDK 9 proporcionó el Java Platform Module System (JPMS) , esta API se incluyó como un módulo de incubadora . Los módulos de incubadora están diseñados para proporcionar nuevas API, pero no las convierten en el estándar Java SE. Los desarrolladores pueden probar la API proporcionando comentarios. Después de realizar los cambios necesarios (esta API se actualizó en JDK 10), la API se puede transferir al módulo principal para formar parte del estándar.


La API de cliente HTTP ahora forma parte del estándar Java SE 11. Esto introduce un nuevo módulo y paquete para el JDK, java.net.http . Clases principales:


  • Httpclient
  • Httprequest
  • HttpResponse
  • Zócalo web

La API se puede usar de forma sincrónica o asincrónica. En modo asíncrono, se utilizan CompletionFutures y CompletionStage.


JEP 320: eliminar los módulos Java EE y CORBA


Con la introducción de JPMS en JDK 9, fue posible dividir el archivo monolítico rt.jar en varios módulos. Una ventaja adicional de JPMS es que ahora puede crear un entorno de tiempo de ejecución Java que incluye solo los módulos necesarios para su aplicación, lo que reduce en gran medida el tamaño general. Con límites claramente definidos, los módulos obsoletos ahora son más fáciles de eliminar de la API de Java. Esto es lo que hace este JEP; El meta módulo java.se.ee incluye seis módulos que ya no serán parte del estándar Java SE 11 y no se incluirán en el JDK.


Módulos remotos:


  • corba ( nota del traductor: descansa en paz arder en el infierno )
  • transacción
  • activación
  • xml.bind
  • xml.ws
  • xml.ws.annotation

Estos módulos se han marcado como obsoletos (@Deprecated) desde JDK 9 y no se incluyeron de forma predeterminada en la compilación o el tiempo de ejecución. Si trató de compilar o ejecutar una aplicación utilizando la API de estos módulos en JDK 9 o JDK 10, entonces habría fallado. Si utiliza la API de estos módulos en su código, deberá proporcionarlos como un módulo o biblioteca por separado. A juzgar por las revisiones, parece que los módulos java.xml que forman parte del soporte de servicios web SOAP de JAX-WS son los que causarán la mayoría de los problemas.


Nueva API pública


Muchas de las nuevas API en JDK 11 son el resultado del hecho de que el módulo de cliente HTTP ahora es parte del estándar, así como la inclusión de Flight Recorder.


Aquí se puede encontrar una lista esquemática completa de cambios de API, incluida una comparación de diferentes versiones del JDK .


A continuación se enumeran todos los métodos nuevos, distintos de los contenidos en los módulos java.net.http y jdk.jfr. Tampoco se enumeran los nuevos métodos y clases en los módulos java.security, que son bastante específicos para los cambios JEP 324 y JEP 329 (hay seis nuevas clases y ocho nuevos métodos).


java.io.ByteArrayOutputStream


  • writeBytes vacío (byte []) : escribe todos los bytes del argumento en OutputStream

java.io.FileReader


Dos nuevos constructores que le permiten especificar un juego de caracteres.


java.io.FileWriter


Cuatro nuevos constructores que le permiten especificar un juego de caracteres.


java.io.InputStream


  • io.InputStream nullInputStream () : devuelve un InputStream que no lee bytes. Al observar este método (y el de OutputStream, Reader y Writer), surge la pregunta de por qué podría ser útil. Puede pensar en ellos como / dev / null , para descartar resultados que no necesita o proporcionar entradas que siempre devuelvan bytes nulos.

java.io.OutputStream


  • io.OutputStream nullOutputStream ()

java.io.Reader


  • io.Reader nullReader ()

java.io.Writer


  • io.Writer nullWriter ()

java.lang.Character


  • String toString (int) : esta es una forma sobrecargada de un método existente, pero se usa int en lugar de char. Int es el punto de código Unicode.

java.lang.CharSequence


  • int compare (CharSequence, CharSequence) : compara dos instancias de CharSequence lexicográficamente . Devuelve un valor negativo, cero o un valor positivo si la primera secuencia es lexicográficamente menor, igual o mayor que la segunda, respectivamente.

java.lang.ref.Reference


  • lang.Object clone () : Debo admitir que este cambio causa confusión. La clase Reference no implementa la interfaz Cloneable, y este método arroja una excepción CloneNotSupportedException. Debe haber una razón para su inclusión, tal vez por algo en el futuro. ( Nota del traductor: hay una discusión sobre StackOverflow , un ticket en OpenJDK )

java.lang.Runtime


java.lang.System


No hay métodos nuevos aquí, pero vale la pena mencionar que el método runFinalizersOnExit () ahora se elimina de ambas clases (puede haber un problema al migrar a JDK 11).


java.lang.String


Creo que este es uno de los aspectos más destacados de las nuevas API en JDK 11. Aquí hay algunos métodos nuevos y útiles.


  • boolean isBlank () : devuelve verdadero si la cadena está vacía o contiene solo espacios, de lo contrario es falso.
  • Líneas de flujo () : devuelve flujo de cadena, extraído de esta cadena, separado por separadores de línea.
  • String repeat (int) : devuelve una cadena cuyo valor es la concatenación de esta cadena, repetida varias veces.
  • String strip () : devuelve una cadena cuyo valor es esta cadena, esto elimina todos los espacios al principio y al final de la cadena.
  • String stripLeading () : devuelve una cadena cuyo valor es esta cadena, mientras elimina todos los espacios al comienzo de la línea.
  • String stripTrailing () : devuelve una cadena cuyo valor es esta cadena, esto elimina todos los espacios al final de la cadena.

Lo más probable es que mire strip () y pregunte: "¿Cómo es esto diferente del método trim () existente?" La respuesta radica en la diferencia en la definición de espacios. ( Nota del traductor: en resumen, strip () entiende mejor Unicode, análisis detallado en StackOverflow )


java.lang.StringBuffer


java.lang.StringBuilder


Ambas clases tienen un nuevo método compareTo () que toma un StringBuffer / StringBuilder y devuelve un int. El método de comparación léxico es similar al nuevo método compareTo () en CharSequence.


java.lang.Thread


No hay nuevos métodos. Los métodos destroy () y stop (Throwable) han sido eliminados. El método stop () , que no toma argumentos, todavía está presente. Puede provocar un problema de compatibilidad.


java.nio.ByteBuffer


java.nio.CharBuffer


java.nio.DoubleBuffer


java.nio.FloatBuffer


java.nio.LongBuffer


java.nio.ShortBuffer


Todas estas clases ahora tienen el método incompatch () , que encuentra y devuelve el índice relativo de la primera discordancia entre este buffer y el buffer pasado.


java.nio.channels.SelectionKey


  • int InterestOpsAnd (int) : establece atómicamente el interés de esta clave (el interés de la clave) en la intersección bit a bit ("y") del conjunto de intereses existente y el valor pasado.
  • int InterestOpsOr (int) : establece atómicamente el interés de esta clave (el interés de la clave) en la unión bit a bit ("o") del conjunto de intereses existente y el valor pasado.

java.nio.channels.Selector


  • int select (java.util.function.Consumer, long) : selecciona y realiza acciones en teclas cuyos canales correspondientes están listos para operaciones de E / S. argumento largo es un tiempo de espera.
  • int select (java.util.function.Consumer) : igual que el anterior, pero sin tiempo de espera.
  • int selectNow (java.util.function.Consumer) : igual que el anterior, solo sin bloqueo.

java.nio.file.Files


  • String readString (Path) : lee todo el contenido de un archivo en una cadena, decodificando desde bytes a caracteres usando la codificación UTF-8.
  • String readString (Path, Charset) : como se indicó anteriormente, con la diferencia de que la decodificación de bytes a caracteres se produce utilizando el Charset especificado.
  • Path writeString (Path, CharSequence, java.nio.file.OpenOption []) : escribe CharSequence en un archivo. Los caracteres se codifican en bytes utilizando la codificación UTF-8.
  • Path writeString (Path, CharSequence, java.nio.file.Charset, OpenOption []) : al igual que arriba, los caracteres se codifican en bytes utilizando la codificación especificada en Charset.

java.nio.file.Path


  • Ruta de (Cadena, Cadena []) : devuelve Ruta desde el argumento de cadena de la ruta o secuencia de cadenas que, cuando se combinan, forman la cadena de ruta.
  • Ruta de acceso (net.URI) : devuelve Ruta desde el URI.

java.util.Collection


  • Object [] toArray (java.util.function.IntFunction) : devuelve una matriz que contiene todos los elementos de esta colección, utilizando la función de generación proporcionada para asignar la matriz devuelta.

java.util.concurrent.PriorityBlockingQueue


java.util.PriorityQueue


  • nulo para cada (java.util.function.Consumer) : realiza la acción aprobada para cada elemento Iterable hasta que se procesen todos los elementos o la acción arroje una excepción.
  • boolean removeAll (java.util.Collection) : elimina todos los elementos de esta colección que también están contenidos en la colección especificada (operación opcional).
  • removeIf booleano (java.util.function.Predicate) : elimina todos los elementos de esta colección que satisfacen el predicado dado.
  • boolean retiene todos (java.util.Collection) : guarda solo los elementos de esta colección que están contenidos en la colección transferida (operación opcional).

java.util.concurrent.TimeUnit


  • conversión larga (java.time.Duration) : convierte la duración pasada a este tipo.

java.util.function.Predicate


  • Predicate not (Predicate) : devuelve el predicado, que es la negación del predicado transmitido.

Esta es una de mis nuevas API favoritas en JDK 11. Como ejemplo, puede convertir este código:


  lines.stream() .filter(s -> !s.isBlank()) 

en


  lines.stream() .filter(Predicate.not(String::isBlank)) 

o si usamos importaciones estáticas:


  lines.stream() .filter(not(String::isBlank)) 

Personalmente, creo que esta versión es más comprensible y concisa.


java.util.Optional


java.util.OptionalInt


java.util.OptionalDouble


java.util.OptionalLong


  • boolean isEmpty () : si no hay valor, devuelve verdadero, de lo contrario falso.

java.util.regex.Pattern


  • Predicate asMatchPredicate () : Creo que podría ser la joya de la nueva API JDK 11. Crea un predicado que verifica si esta plantilla coincide con la cadena de entrada dada.

java.util.zip.Deflater


  • int deflate (ByteBuffer) : comprime la entrada y llena el búfer especificado con ella.


  • int deflate (ByteBuffer, int) : comprime la entrada y llena el búfer especificado con ella. Devuelve la cantidad real de datos comprimidos.


  • void setDictionary (ByteBuffer) : establece el diccionario especificado para la compresión de bytes en este búfer. Esta es una forma sobrecargada de un método existente que un ByteBuffer ahora puede aceptar, en lugar de una matriz de bytes.


  • void setInput (ByteBuffer) : establece la entrada a comprimir. También una forma sobrecargada de un método existente.



java.util.zip.Inflater


  • int inflate (ByteBuffer) : descomprime bytes en el búfer especificado. Devuelve el número real de bytes descomprimidos.
  • void setDictionary (ByteBuffer) : establece el diccionario especificado en bytes en este búfer. La forma sobrecargada de un método existente.
  • void setInput (ByteBuffer) : establece la entrada para la descompresión. La forma sobrecargada de un método existente.

javax.print.attribute.standard.DialogOwner


Esta es una nueva clase en JDK 11. Se utiliza para admitir una solicitud de diálogo de impresión o configuración de página. Debe mostrarse en la parte superior de todas las ventanas o en una ventana específica.


javax.swing.DefaultComboBoxModel


javax.swing.DefaultListModel


  • void addAll (Colección) : agrega todos los elementos presentes en la colección.
  • void addAll (int, Collection) : agrega todos los elementos presentes en la colección, comenzando desde el índice especificado.

javax.swing.ListSelectionModel


  • int [] getSelectedIndices () : Devuelve una matriz de todos los índices seleccionados en el modelo seleccionado, en orden ascendente.
  • int getSelectedItemsCount () : devuelve el número de elementos seleccionados.

jdk.jshell.EvalException


  • jshell.JShellException getCause () : devuelve un contenedor de causa arrojable en el cliente de ejecución representado por una EvalException, o nulo si la causa no existe o es desconocida.

Nuevas características (no API pública)


JEP 181: Control de acceso basado en nidos


Java (y otros lenguajes) admite clases anidadas a través de clases internas. Para el correcto funcionamiento, el compilador debe realizar algunos trucos. Por ejemplo:


  public class Outer { private int outerInt; class Inner { public void printOuterInt() { System.out.println("Outer int = " + outerInt); } } } 

El compilador modifica esto para crear algo como esto antes de hacer la compilación:


  public class Outer { private int outerInt; public int access$000() { return outerInt; } } 

  class Inner$Outer { Outer outer; public void printOuterInt() { System.out.println("Outer int = " + outer.access$000()); } } 

Aunque, lógicamente, la clase interna es parte del mismo código que la clase externa, se compila como una clase separada. Por lo tanto, esto requiere un método sintético ("puente"), que debe ser creado por el compilador para proporcionar acceso al campo privado de la clase externa.


Este JEP representa el concepto de un "zócalo", donde dos miembros del mismo zócalo (externo e interno de nuestro ejemplo) son vecinos. Se agregaron dos nuevos atributos en el formato de archivo * .class: NestHost y NestMembers. Estos cambios también son útiles para otros lenguajes compilados por bytecode que admiten clases anidadas.


Esta característica proporciona tres nuevos métodos para java.lang.Class:


  • Clase getNestHost ()
  • Clase [] getNestMembers ()
  • boolean isNestmateOf (clazz)

Esta característica también requería cambios en la Especificación de máquina virtual Java (JVMS) , particularmente en la sección 5.4.4 "Control de acceso".


JEP 309: Constantes dinámicas de archivo de clase


Este JEP describe la extensión del formato de archivo * .class para admitir el nuevo formulario con el grupo constante CONSTANT_Dynamics (a menudo denominado condy en las presentaciones). La idea de una constante dinámica parece ser un oxímoron, pero, de hecho, se puede considerar como un valor final en Java. El valor del grupo constante no se establece en la etapa de compilación (a diferencia de otras constantes), pero el método bootstrap se usa para determinar el valor en tiempo de ejecución. Por lo tanto, el valor es dinámico, pero dado que su valor se establece solo una vez, también es constante.


Esta característica será principalmente útil para aquellos que están desarrollando nuevos lenguajes y compiladores. Quién generará los archivos bytecode y * .class para ejecutar en la JVM. Esto simplificará algunas tareas.


Esta característica proporciona una nueva clase java.lang.invoke.ConstantBootstraps con nueve métodos nuevos. No los enumeraré todos aquí; Estos son métodos de arranque para constantes calculadas dinámicamente.


Esta característica requería cambios en el JVMS, en particular, cómo se usa el código de byte de invocación especial y la sección 4.4 de The Constant Pool.


JEP 315: Mejora la intrínseca Aarch64


Este fue el JEP aportado por Red Hat. La JVM ahora puede usar instrucciones más especializadas disponibles en el conjunto de comandos Arm 64. En particular, esto mejora el funcionamiento de los métodos sin (), cos () y log () de la clase java.lang.Math.


JEP 318: El recolector de basura Epsilon


Red Hat también contribuyó a este PEC. ¡El recolector de basura Epsilon es algo inusual ya que no recolecta basura! Asignará nueva memoria si es necesario al crear nuevos objetos, pero no libera el espacio ocupado por objetos sin enlaces.


Parecería, entonces, ¿cuál es el punto? Hay al menos dos usos:


  • En primer lugar, este recopilador está diseñado para garantizar que los nuevos algoritmos de GC se evalúen en términos de su impacto en el rendimiento. La idea es ejecutar una aplicación de ejemplo con Epsilon GC y generar una métrica. Se incluye un nuevo algoritmo GC, se ejecutan las mismas pruebas y se comparan los resultados.
  • Para tareas muy cortas o de corta duración (piense en una función sin servidor en la nube), donde puede asegurarse de no exceder la memoria asignada al espacio de almacenamiento dinámico. Esto puede mejorar el rendimiento al eliminar la sobrecarga (incluida la recopilación de estadísticas necesarias para decidir si ejecutar el recopilador) en el código de la aplicación.

Si se agota el espacio de almacenamiento dinámico, la operación JVM posterior se puede configurar de una de estas tres maneras:


  • Se llama a un OutOfMemoryError regular.
  • Restablecer montón
  • Imposible detener la JVM y posiblemente realizar una tarea externa (por ejemplo, iniciar el depurador).

JEP 324: Acuerdo clave con Curve25519 y Curve448


Los estándares criptográficos cambian y mejoran constantemente. En este caso, el esquema Diffie-Hellman existente con una curva elíptica se reemplaza por Curve25519 y Curve448. Este es un esquema de acuerdo clave definido en RFC-7748.


JEP 327: Unicode 10


La plataforma Java admite Unicode para permitir el procesamiento de todos los juegos de caracteres. Dado que Unicode se ha actualizado a la versión 10 , el JDK también se ha actualizado para admitir esta versión del estándar.


Siempre me intriga ver qué incluyen los desarrolladores de Unicode en las nuevas versiones. Unicode 10 tiene 8.518 nuevos personajes. Esto incluye el símbolo de Bitcoin, el conjunto de caracteres Nüshu (utilizado por las mujeres chinas para escribir poemas) y Soyombo y la Plaza Zanabazar (son los caracteres utilizados en textos budistas históricos para escribir idiomas sánscrito, tibetano y mongol). También se han agregado muchos otros Emoji, incluido el tan esperado (aparentemente) Colbert Emoji .


Recuerde, comenzando con JDK 9, puede usar UTF-8 en archivos de propiedades (.properties). Esto significa que cualquier carácter Unicode puede usarse en dichos archivos. Incluyendo Emojis. O Nüshu


JEP 328: Registrador de vuelo


Flight Recorder — JVM. JDK 11 Oracle JDK. , Oracle Oracle JDK OpenJDK, OpenJDK.


JEP :


  • API
  • , JVM HotSpot JDK

: jdk.jfr jdk.management.jfr.


JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithms


JEP 324, , JDK. ChaCha20 ChaCha20-Poly1305, RFC 7539. ChaCha20 — , , RC4.


JEP 331: Low-overhead Heap Profiling


, JEP, Google. Java JVM.


:


  • ,
  • ( , GC VM)
  • Java.

JEP 332: Transport Layer Security (TLS) 1.3


TLS 1.3 (RFC 8446) " " TLS . JDK , Datagram Transport Layer Security (DTLS).


JEP 333: ZGC A Scalable, Low Latency Garbage Collector


, , () . ( , Weak Generational Hypothesis ) ( ) GC . "" , . .


ZGC — region-based ( G1), NUMA aware compacting . .


pauseless , C4 Zing JVM.


JEP 335: Deprecate the Nashorn Scripting Engine


Nashorn JDK 8 Rhino Javascript . , Nashorn API jjs Java. , . Graal VM , , .


JEP 336: Deprecate the Pack200 Tools and APIs


Pack200 — JAR-, Java SE 5.0. JPMS JDK 9 Pack200 JDK. pack200 unpack200 API Pack200 java.util.jar JDK. , .


Conclusiones


JDK 11 — LTS JDK ( ). , , , , JVM , .


Zulu JDK 11 !


JDK 11?


( . : , )

Source: https://habr.com/ru/post/es424683/


All Articles