Con regularidad similar a un reloj atómico, la última versión de Java, JDK 22, fue lanzado la semana pasada. Aunque esta no es una versión de soporte a largo plazo (LTS), no hay nada que le impida utilizarla en producción y contiene algunas características nuevas e interesantes.
Profundicemos y veamos qué nos trae esto.
Las nuevas características para la plataforma Java se definen a través de Propuestas de mejora de JDK (JEP), y JDK 22 contiene 12 de estos. Casualmente, en las últimas 13 versiones de Java, desde el cambio a una cadencia de seis meses, el número promedio de JEP (al entero más cercano) también es 12. ¡Podrías, por lo tanto, describir esto como una versión promedio!
Desglosando esto aún más, tenemos cuatro funciones finales y ocho funciones de vista previa o módulos de incubadora.
Cambios en el lenguaje Java
DAR 447: Declaraciones anteriores super()
[preview]. Como lenguaje orientado a objetos, Java ofrece la capacidad de extender otra clase (no final) y heredar tanto el estado como el comportamiento (cuando esté permitido). Para que esto funcione de manera confiable, los constructores de las clases deben llamarse en orden de arriba hacia abajo para evitar que los constructores de las subclases interfieran con los de las superclases. Cuando un desarrollador decide realizar una llamada explícita al constructor de la superclase, esta debe ser la primera declaración.
Esto impone algunas limitaciones, que pueden dar lugar a un código más complejo de lo deseado. El más obvio de ellos es la imposibilidad de realizar una prueba de los parámetros del constructor antes de llamar al constructor de la superclase. Si una prueba genera una excepción, la llamada al constructor de la superclase se convierte en una sobrecarga técnicamente innecesaria.
JEP 447 introduce una forma controlada de permitir declaraciones antes de una llamada a super()
. Cualquier referencia a la this
o super
Las referencias a objetos generarán errores ya que el objeto al que se hace referencia no se habría inicializado por completo. Hay varias otras restricciones que se describen en detalle en este JEP.
DAR 456: Patrones y variables sin nombre. Introducida como una función de vista previa en JDK 21, ahora es definitiva sin ningún cambio.
Esta característica permite a los desarrolladores utilizar un único guión bajo. _
para representar una variable que no se utilizará. En lugar de tener variables con nombre que saturan nuestro código y hacen que sea más difícil ver lo que está sucediendo, podemos mantener la sintaxis correcta para una construcción y ayudar a la legibilidad.
Un ejemplo sencillo es un foreach
bucle de estilo que itera sobre una colección pero no utiliza el valor recuperado:
for (String name : userList) userCount++;
Esto se puede simplificar a:
for (String _ : userList) userCount++;
Este es un ejemplo bastante trivial, pero cuando se aplica a patrones, su valor se vuelve más claro. Usando patrones de registros compuestos, que son una forma de patrón de deconstrucción, podríamos tener algo como esto:
public void printTopLeftX(Rectangle r) { if (r instanceof ColourRectangle(ColourPoint( Point(double x, double y), Colour c), ColourPoint bottomRight)) System.out.println(x); }
Como lo único que utilizamos es el valor de x, todas las demás variables (incluida su definición de tipo) son superfluas y hacen que el código sea muy denso. Usando patrones sin nombre, podemos reescribir esto como:
public void printTopLeftX(Rectangle r) { if (r instanceof ColourRectangle(ColourPoint(Point(var x, _), _), _) ) System.out.println(x); }
Estos también se pueden utilizar en la coincidencia de patrones para expresiones switch y lambda.
DAR 459: Plantillas de cadenas (vista previa). Introducida como una función de vista previa en JDK 21, todavía está en vista previa sin cambios visibles para los desarrolladores.
La construcción de cadenas en Java se puede lograr de varias maneras diferentes: mediante la concatenación de cadenas y el uso de clases de biblioteca como StringBuilder
y String.format()
. Las plantillas de cadenas proporcionan una forma simplificada de expresar cadenas que contienen valores que se calculan en tiempo de ejecución.
Ahora tenemos un procesador de plantilla de cadena, STR
que puede realizar interpolación de cadenas.
Como ejemplo simple, podemos insertar valores:
String name = "Simon"; String info = STR." My name is \{name}";
El verdadero poder de las plantillas de cadenas es que puedes realizar una interpolación mucho más sofisticada, por ejemplo, usando llamadas a métodos:
String s = STR." We are here \{ // Method call DateTimeFormatter .ofPattern("B") .format(LocalTime.now()) } learning Java";
Observe que podemos sangrar el código como queramos sin afectar la cadena generada e incluso incluir comentarios.
DAR 463: Clases e instancias declaradas implícitamente main
métodos [preview]. Esto se introdujo como una característica de vista previa en JDK 21 y continúa así con algunos cambios significativos.
Escribir incluso la aplicación Java más simple requiere mucha ceremonia (o código repetitivo). Para el habitual «hola mundo», necesitamos todo esto:
public class Hello { public static void main(String[] args) { System.out.println(“Hello, World!”); } }
JEP 463 permite que un programa utilice una instancia main
método, que no necesita ser marcado como static
o public
. También proporciona una unidad de compilación tal que ya no necesitamos definir explícitamente la clase. El efecto general de estos cambios es reducir nuestra aplicación a:
void main(){ System.out.printIn("Hello, World!"); }
Esto será de utilidad limitada para desarrolladores experimentados, pero ayudará a quienes se inician en Java.
Cambios de biblioteca
DAR 454: Función externa y API de memoria. Introducida inicialmente como una función de vista previa en JDK 19, ahora es una función final.
Esta API es parte del Proyecto Panamá y proporciona un reemplazo más simple para la Interfaz Nativa de Java (JNI). Estas API proporcionan formas estándar de interactuar con la memoria nativa y bibliotecas externas, que se compilan directamente en código nativo en lugar de códigos de bytes. La interacción bidireccional es posible a través de llamadas descendentes (de Java a funciones nativas) y llamadas ascendentes (devoluciones de llamada del código nativo al código Java).
Una herramienta adicional, jextract
, se puede utilizar para generar código para acceder a una biblioteca externa. Esto no está incluido de forma predeterminada en el JDK, pero está disponible como código fuente en OpenJDK.
DAR 457: API de archivo de clase [preview]. Para la mayoría de los desarrolladores, esta no será una API interesante. Procesar archivos de clase es algo que el JVM obviamente debe hacer (para cargar y ejecutar aplicaciones) y también es algo que requieren muchos marcos y bibliotecas.
El objetivo de esta API es estandarizar y simplificar la forma en que los usuarios pueden interactuar con los archivos de clase.
DAR 460: API vectorial [preview]. Esta API tiene el récord de ser la característica de vista previa más larga, estando en su séptima iteración en JDK 22.
Los vectores, en este caso, se refieren a registros muy amplios disponibles en todas las CPU modernas. Usando una técnica llamada instrucción única, datos múltiples (SIMD), se pueden cargar múltiples elementos de una matriz en el vector y se puede realizar la misma operación (como sumar o restar un valor) en un solo ciclo de reloj. Este procesamiento paralelo puede conducir a importantes mejoras de rendimiento para operaciones numéricamente intensivas.
La API proporciona formas para que el desarrollador especifique cómo se deben almacenar los valores en los vectores y las operaciones que se requieren en ellos.
Para situaciones simples, el compilador interno justo a tiempo (JIT) de la JVM reconocerá dónde se pueden usar operaciones vectoriales y las aplicará automáticamente. Para situaciones más complejas, por ejemplo, donde un bucle incluye una prueba condicional para un cálculo, esta API será útil.
Alternativamente, Azul Platform Prime Zing JVM utiliza un compilador JIT de reemplazo llamado Falcon. Basado en el código abierto proyecto llvmesto puede reconocer muchas más situaciones en las que se pueden utilizar operaciones vectoriales y ofrecer un mejor rendimiento sin modificaciones de código.
DAR 461: recolectores de corrientes [preview]. La API de transmisiones se introdujo en JDK 8 y, combinada con expresiones lambda, proporcionó un estilo de programación más funcional que antes no había sido posible en Java.
Las secuencias constan de una fuente que proporciona elementos que pueden pasar a través de cero o más operaciones intermedias antes de que se genere un resultado o efecto secundario mediante una operación de terminal.
Para el funcionamiento del terminal, es posible definir su propia funcionalidad a través de Stream::collector
. Aunque existe un rico conjunto de operaciones intermedias, estas son fijas y un desarrollador no puede ampliarlas.
La API del recopilador de Stream ahora proporciona una forma de definir una nueva operación intermedia.
Un recolector se define por cuatro funciones: un inicializador opcional, un integrador, un combinador opcional y un finalizador opcional. Al usarlos, los desarrolladores tienen total flexibilidad sobre cómo se procesan los elementos de entrada al recopilador y la salida que se genera para pasar a la siguiente operación intermedia o terminal.
DAR 462: Simultaneidad estructurada [preview]. Esto se introdujo por primera vez en JDK 19 como un módulo de incubadora y ha sido una característica de vista previa desde JDK 21. No se han realizado cambios en esta versión.
Por su propia naturaleza, escribir código multiproceso confiable es un desafío. A lo largo de la historia de Java, hemos tenido muchas características nuevas destinadas a hacer esta tarea al menos algo más sencilla. Las utilidades de concurrencia, el marco de unión de bifurcación y los flujos paralelos han proporcionado soluciones a diferentes tipos de situaciones de subprocesos múltiples.
La simultaneidad estructurada, parte de Project Loom, trata múltiples tareas que se ejecutan en diferentes subprocesos como una única unidad de trabajo. Esto hace que tanto el manejo de errores como la cancelación sean más sencillos de manejar.
DAR 464: Valores con alcance [preview]. Esto se introdujo como una característica de vista previa en JDK 21 y continúa en JDK 22 sin cambios.
Los valores con alcance también están relacionados con Project Loom y proporcionan una alternativa a las variables locales de subproceso. La diferencia fundamental es que, como valor y no como variable, son inmutables.
Las variables locales de subprocesos tienen más complejidad de la que normalmente se necesita y tienen un costo de recursos sustancial asociado. Dado que los subprocesos virtuales permiten una escalabilidad de órdenes de magnitud mayores que los subprocesos de la plataforma, este costo de recursos puede convertirse en un factor limitante. Los valores con alcance resuelven este problema de una manera que permite a los desarrolladores la flexibilidad que necesitan para la lógica de aplicaciones multiproceso.
JVM y otros cambios
DAR 423: Fijación de región para G1. Esta es una mejora en la forma en que funciona el recolector de basura (GC) G1 que reduce la latencia cuando se usa JNI.
A diferencia del código Java, las interacciones JNI pueden utilizar punteros explícitos a objetos en el montón. No es posible reubicar esos objetos dentro del montón cuando un subproceso Java está ejecutando una región crítica del código JNI. Para evitar este problema, G1 desactiva GC durante las regiones críticas, lo que puede provocar una mayor latencia, ya que otros subprocesos que no sean JNI se bloquearán si activan un GC.
Este cambio permite que G1 GC se ejecute incluso cuando un subproceso está en una región crítica fijando regiones de memoria utilizadas por el código JNI pero permitiendo que otras sean reubicadas y recopiladas.
DAR 458: inicia programas de código fuente de varios archivos. En JDK 11, JEP 330 introdujo la capacidad de ejecutar un único archivo fuente sin la necesidad de compilarlo directamente. Esto está relacionado con la simplificación de la introducción a Java, como se analiza en JEP 463 anteriormente.
JEP 458 mejora la java
lanzador de aplicaciones permitiéndole ejecutar un programa suministrado como varios archivos de código fuente Java en lugar de solo uno. La mayoría de los desarrolladores utilizan un IDE para el desarrollo de proyectos y jshell
para experimentar con fragmentos de código.
Esta característica será de gran utilidad para aquellos que recién comienzan su viaje para aprender a programar en Java.
Por encima del promedio
Como puede ver, JDK 22 contiene una cantidad promedio de funciones nuevas, pero es mejor que el promedio en lo que ofrecen esas funciones. Azul tiene descargas gratuitas de nuestras compilaciones Zulu de OpenJDK Community Edition que puede instalar y experimentar. ¿Por qué no darle una oportunidad?
Simon Ritter es CTO adjunto y campeón de Java en Azul.
—
New Tech Forum ofrece un lugar para que los líderes tecnológicos, incluidos proveedores y otros contribuyentes externos, exploren y debatan la tecnología empresarial emergente con una profundidad y amplitud sin precedentes. La selección es subjetiva y se basa en nuestra elección de las tecnologías que creemos que son importantes y de mayor interés para los lectores de InfoWorld. InfoWorld no acepta garantías de marketing para su publicación y se reserva el derecho de editar todo el contenido aportado. Envia todo consultas a doug_dineley@foundryco.com.
Copyright © 2024 IDG Communications, Inc.