La nueva y esperada versión de uno de los lenguajes de programación más populares alrededor del mundo ya está aquí y trae consigo una serie de cambios y mejoras que merece la pena analizar. Desde mejoras en el rendimiento hasta cambios en la estructura básica de la sintaxis del código, Java 25 marca un antes y un después en la forma en la que los desarrolladores utilizarán este longevo lenguaje que acompaña al mundo de la informática desde 1995.
En las siguientes líneas se procede a hablar de todas las características importantes con las que cuenta tanto a nivel de plataforma como de desarrollo, centrándonos principalmente en este último apartado. Pero antes de comenzar a adentrarse de lleno en todas las mejoras que trae consigo la nueva versión, no está de más recordar que Java ha vivido una transformación progresiva y constante en estos últimos años. Ha adaptado su plataforma para ofrecer una programación más expresiva, segura y moderna, siendo Java 25 el que ha dado las pinceladas más recientes, aunque existan a sus espaldas una serie de importantes versiones a destacar que han transformado poco a poco Java en el famoso lenguaje que es hoy día.
La evolución del lenguaje: de Java 17 a Java 25
Para contar la evolución hasta Java 25 se puede partir de Java 17, ya que esta es la versión considerada como la base moderna del lenguaje, donde sus cambios estabilizaron aquello que se introdujo en versiones anteriores, así como también comenzaron los cimientos de las mejoras que se vieron en Java 21 y se ven en este nuevo Java 25.
El nuevo punto de partida: Java 17
Una de las grandes mejoras del lenguaje fueron las Sealed Classes (o clases selladas en español), que fueron formalmente añadidas, permitiendo tanto a estas como a las interfaces ya existentes restringir qué otras clases o interfaces podían extender o implementar otras; es decir, controlar mejor la herencia en nuestro código, mejorando así la seguridad y el control sobre las jerarquías. Otro gran cambio que presentó en su sintaxis fue el uso de Pattern Matching (coincidencia de patrones) para estructuras condicionales de tipo switch. Esto permitió usar patrones y condicionales directamente, haciendo el código más escueto, limpio y fácil de entender.
En lo que respecta al rendimiento y las mejoras en la plataforma, en esta versión al fin se introdujo soporte oficial para macOS en arquitecturas ARM, así como un nuevo pipeline de renderizado para el mismo sistema operativo, lo que mejoró el rendimiento en los equipos que contaran con él. Aparte de esto, se realizaron mejoras en los Random Generators (generadores aleatorios), añadiendo una nueva API con la interfaz RandomGenerator, mejorando la capacidad de intercambio entre algoritmos y el soporte en operaciones basadas en flujos, entre otras.
También, como es común, se realizaron algunas mejoras en la seguridad y la limpieza del código con cosas como los filtros de deserialización, encargados de mejorar la seguridad al deserializar objetos (reconstruir un objeto a su estado anterior), o la encapsulación fuerte de los internos (que se trata de las clases internas del propio JDK), mejorando la seguridad y la mantenibilidad al permitir solo el acceso a aquellas APIs de Java que sean públicas.
Todo esto marcó el inicio de la limpieza y modernización del lenguaje, enfocándose en seguridad, coherencia y rendimiento.
Mejorando lo ya establecido: Java 21
Continuando con las mejoras durante la evolución del lenguaje Java, hay que mencionar los Record Patterns, un sistema que permitió extraer directamente componentes sin necesidad de un código complejo. Otro gran añadido a su sintaxis fue extender el Pattern Matching (la coincidencia de patrones que ya venía con Java 17) para switch, permitiendo así, con menor cantidad de código, que se puedan comparar no solo valores constantes, sino también tipos, campos concretos de los objetos, validaciones y clases selladas. Algo más a destacar son los Unnamed Patterns y Variables, que se tratarían de un nuevo tipo de variable y patrón sin nombre, evitando así que el compilador avise de error en caso de no utilizarse, reduciendo la complejidad del código. Al igual que las Unnamed Patterns, se añadieron las Unnamed Classes y se simplificó el método main. Esta característica es una de varias destinadas a crear una mejor curva de aprendizaje en el lenguaje y permitir una entrada sencilla a nuevos desarrolladores, concretamente estableciendo una creación de clases simplificada.
En cuanto a rendimiento, se puede destacar otra mejora relacionada con simplificar y facilitar el lenguaje. En esta se establecieron los Scoped Values, que se utilizan para compartir datos inmutables entre hilos de manera más controlada y con un alcance concreto, creando así una alternativa a ThreadLocal. También se añadieron mejoras al manejo de colecciones con Sequenced Collectors (colecciones con secuencia), permitiendo usar nuevos métodos para acceder al orden lógico (primera posición, última, etc.) de manera unificada y sin necesidad de índices o iteradores manuales. Pero sin lugar a dudas, lo más destacable en esta sección son los Virtual Threads: probablemente la adición más importante de Java 21. Solucionan el problema principal de usar hilos en Java, ya que estos eran costosos debido a que cada uno estaba ligado a un hilo del sistema operativo. Gracias a esta mejora, los hilos son gestionados por la JVM (máquina virtual de Java), haciéndolos más ligeros, baratos y escalables que en versiones anteriores.
De nuevo se realizaron cambios en la seguridad y el entorno. Se añadieron cosas como el Key Encapsulation Mechanism, una API estándar para los mecanismos de encapsulación de claves, mejorando la seguridad en el intercambio de claves. También se añadió la preparación para deshabilitar la carga dinámica de agentes (que son componentes utilizados para modificar o monitorear el comportamiento de una aplicación), pues al ser algo peligroso y difícil de controlar, Java 21 se encargó de advertir de su uso como algo negativo, preparando el terreno para un futuro en el que se prohíba su uso de manera definitiva.
En esta versión también se realizaron cambios importantes en lo que respecta a la interoperabilidad y la eficiencia, creando Foreign Function & Memory, una mejora en la línea de evolución de Java en torno al Pattern Matching, proporcionando una API para que Java pueda interactuar con código nativo (de otros lenguajes como C) y con memoria fuera del heap; la Vector API, que permitiría extraer directamente componentes de un record dentro de un patrón sin necesidad de nombrar el record completo, mejorando el código al hacerlo más preciso y ayudando así en la creación de código genérico; o la Generational ZGC, que introduce una nueva API para poder manejar los archivos .class (en ejecución) de forma nativa y segura.
Con esto se resumen las principales características de Java 21 que, cerrando el ciclo iniciado por Java 17, eliminaron limitaciones históricas del lenguaje, introdujeron nuevos paradigmas de concurrencia con hilos virtuales y simplificaron el código sin sacrificar robustez.
Un Java más sencillo, más potente y más moderno
Y ahora, sobre las bases asentadas en Java 17 y junto con todas las mejoras, añadidos y optimizaciones realizadas en las versiones posteriores, nos encontramos ante Java 25. Esta versión no busca reinventar el lenguaje, sino perfeccionarlo. Su meta es consolidar la eficiencia de las diferentes APIs y mejorar la experiencia tanto para nuevos desarrolladores como para preparar el terreno para lo que nos depara: entornos cloud e IA.
A continuación, se listarán las mejoras más importantes (tanto las lanzadas en esta versión como las que se tratan de previews, funcionalidades no confirmadas como permanentes) en lo que respecta a la programación, acompañadas de pequeños ejemplos prácticos:
Primitive Type in Patterns (Preview):
De nuevo existe una mejora en el Pattern Matching, concretamente la que afecta a los tipos primitivos (como pueden ser int, double, boolean…). Ahora se permitirá escribir switch y comprobaciones más limpias sin conversiones manuales en los mismos, mejorando la legibilidad en la lógica condicional.
Comprobación en Java 21, menos legible y simple
Nueva forma en Java 25 con el Pattern Matching mejorado
Module Import Declarations:
Siguiendo con las simplificaciones, ahora Java permitirá importar módulos enteros, sin necesidad de múltiples sentencias import.
Forma de importar en Java 21, más tediosa y extensa
Figura 1: Nueva forma en Java 25 que reduce el espacio al poder importar módulos completos
Compact Source Files & Instance Main Methods:
Otra simplificación añadida permitirá crear archivos fuente más compactos al definir métodos main directamente en instancias. Esto resultará especialmente útil en el ámbito educativo, donde es más común realizar scripts cortos.
Método main básico en Java 21 con mayor sintaxis a tener en cuenta
Nuevo método en Java 25, más compacto
Flexible Constructor Bodies:
Anteriormente Java no permitía ejecutar código antes de llamar a super() o this(), pero tras este cambio sí se permitirá, ayudando en la flexibilidad y la configuración previa.
Necesidad en Java 21 de llamar a super() con antelació
Nueva sintaxis de Java 25 más permisiva con el orden
Structured Concurrency (Preview):
Extendiendo el importante trabajo inicial creado con los Virtual Threads de Java 21, ahora se permitirá manejar grupos de tareas concurrentes con una sola unidad lógica, incluyendo el manejo de errores y su cancelación.
Cómo se manejaba la concurrencia en Java 21, de manera más manual
EnJava 25 podemos agrupar subtareas en scopes para controlar su ciclo de vida completo
Scoped Values:
Otra adición que mejorará el uso de hilos, pues se trata de un sustituto de ThreadLocal que ayudará a compartir valores entre diferentes hilos de forma segura y controlada, evitando memory leaks. En resumidas cuentas, es la forma que ha tenido Java de adaptar el uso de contextos al modelo de concurrencia moderna que vino con los virtual threads y para el que Java aún no estaba preparado en todos sus ámbitos.
Ejemplo de su uso en Java 21
EnJava 25 podemos agrupar subtareas en scopes para controlar su ciclo de vida completo
En Java 25 se facilita la gestión además de volverse más segura
Además, ya no hay que preocuparse de los problemas que atañen al uso de poolers de hilos junto
con ThreadLocal, pues a partir de ahora se podrá sustituir también por Scoped Values en estos
casos, asegurando el uso de los datos de forma temporal, limpia y segura:
Uso de Scoped Values sustituyendo a ThreadLocal en una operación con Thread Pool
Vector API:
En esta adición se mejorará la API de vectores para operaciones paralelas a nivel de CPU, optimizando sus cálculos (matemáticos, gráficos, IA…), lo que ayudará a aplicaciones de alto rendimiento o análisis numérico.
Bucle normal en Java 21 sin optimización de cálculo
Uso de la nueva API en Java 25 para hacer la suma en paralelo y con instrucciones SIMD nativas
Key Derivation Function API:
Se introduce esta nueva API estándar, que se encargará de derivar claves criptográficas de forma segura, permitiendo así gestionarlas sin necesidad de librerías externas.
Uso de APIs externas para funciones de derivación de claves
Uso de la nueva API estándar de Java 25 más segura, directa y explícita
Compact Object Headers:
Se reducirá el tamaño de los headers de objetos en memoria de 12/16 a 8 bytes, mejorando la eficiencia y siendo especialmente notorio en aplicaciones con millones de instancias, donde podremos ver una reducción de aproximadamente el 30 % del uso de CPU.
Ahead-of-Time Optimizations:
Se hará más sencillo crear las denominadas ahead-of-time caches, cachés generadas en tiempo de compilación o preejecución que ahorran tiempo al ejecutar las aplicaciones Java. Esta optimización permitirá un arranque más rápido, lo cual podrá ser especialmente importante en microservicios o entornos donde el tiempo sea una prioridad.
Estas son, a grandes rasgos, las nuevas características que presenta el reciente Java 25 para los desarrolladores, donde se puede ver cómo claramente han basado su avance en la simpleza, limpieza y facilidad de uso tanto para nuevos aprendices del lenguaje como para sus más veteranos defensores.
Java 25 no se trata de una versión más. Es la confirmación de que el lenguaje ha sabido adaptarse sin traicionar su esencia. Después de casi tres décadas, sigue siendo una plataforma viva, confiable y en plena evolución
Rubén Gadea
Software Technician
ALTIA