Profile Software Services

JDK 25 (Java 25) explicado: mejoras clave para desarrolladores/as

Con JDK 25 llega una de las versiones más esperadas de Java. Nuevas sintaxis, menos código repetitivo y mejoras pensadas para hacer el día a día del desarrollador mucho más sencillo.

Introducción

¿Quién dijo que Java estaba “viejo”?
En cada proyecto siempre aparece esa conversación:

La realidad es otra. Java 25 (JDK 25) demuestra que el lenguaje no sólo sigue vivo, sino que se reinventa con cada release. En esta versión encontramos mejoras que simplifican el código, hacen nuestras aplicaciones más concurrentes y eliminan viejos dolores de cabeza.

Y para rematar, llega un bonus track que muchos estábamos esperando para acabar con nuestro principal quebradero de cabeza cuando usamos Java: JSpecify, el estándar para nullability, que ahora contará con soporte oficial en Spring Framework 7.


Sí, el temido NullPointerException está cada vez más cerca de desaparecer y es un gran paso para poder minimizar al máximos estos errores en tiempo de Runtime.

Código en Java 25 (JDK 25)

Para ilustrar las novedades de JDK 25, vamos a tomar un fragmento de código sencillo sobre una jerarquía de animales. A través de este ejemplo veremos, de manera progresiva, cómo aplicar las distintas mejoras que aporta esta versión del lenguaje.

Cada sección se centrará en una característica concreta: desde la deconstrucción en patrones dentro de switch, pasando por el uso de _ para valores no utilizados, hasta la posibilidad de agrupar alternativas en un mismo caso o la simplificación del método main con construcciones más limpias.

El objetivo es que, más allá de la teoría, podamos visualizar en código real cómo estas mejoras hacen que nuestro día a día con Java sea más claro, conciso y expresivo.

Código en Java 25 (JDK 25)

1. Pattern Matching más expresivo en JDK 25

El pattern matching es una de las áreas donde Java más ha evolucionado en los últimos lanzamientos. Con JDK 25, esta característica alcanza un nuevo nivel de expresividad gracias a la incorporación de diferentes funcionalidades que pasamos a describir a continuación.

Deconstruction en patrones dentro de switch

Una de las novedades más potentes de JDK 25 es la posibilidad de deconstruir directamente un record en la propia etiqueta de un switch.

Hasta ahora, cuando usábamos pattern matching en un switch, podíamos distinguir el tipo, pero teníamos que capturar el objeto completo y después acceder a sus métodos para extraer la información. Con esta mejora, los componentes del record se desestructuran automáticamente y quedan disponibles como variables locales en cada rama, lo que reduce el código repetitivo y hace que la lógica sea más concisa, expresiva y legible.

Qué había antes:


En versiones previas, aunque ya teníamos pattern matching, había que capturar el objeto entero y luego llamar a sus métodos para obtener los datos.

Qué añade JDK 25:


Ahora podemos deconstruir el record directamente en el patrón del switch:

Esta funcionalidad hace el código más declarativo y elimina el ruido de getters.
Es la primera vez que podemos acceder directamente a los componentes de un record en el propio patrón del switch.

Uso patrón anónimo

Otra mejora incorporada en JDK 25 es el uso del patrón “_” dentro de la deconstrucción de records.

En muchos casos necesitamos extraer solo parte de la información de un objeto y no nos interesa el resto de los campos. Antes estábamos obligados a declararlos igualmente como variables locales, aunque luego no los usáramos, lo que generaba ruido en el código e incluso warnings del compilador por variables sin utilizar.

Con el nuevo patrón “_”, podemos ignorar explícitamente aquellos valores que no necesitamos, manteniendo el switch más claro y expresivo, y documentando la intención de que ciertos datos son irrelevantes para esa rama.

A continuación mostraremos un ejemplo práctico de cómo simplifica el código esta nueva sintaxis.

Qué había antes:
Si un valor no me interesaba, tenía que declararlo igual (intellij lo marca name no es usado).

Qué añade JDK 25:
Puedo ignorar explícitamente los campos que no voy a usar con _:

Con ello conseguimos mejorar:

Agrupación de alternativas en el switch

Otra de las mejoras que incorpora Java 25 es la posibilidad de agrupar varias alternativas dentro de un mismo case en el switch.

Hasta ahora, cuando distintos valores o tipos debían ejecutar la misma lógica, era necesario repetir varias ramas casi idénticas, lo que generaba código duplicado y menos legible. Con esta nueva sintaxis, podemos combinar alternativas separadas por comas y asociarlas a una única acción.

El resultado es un switch más compacto, expresivo y fácil de mantener, especialmente útil cuando varios casos comparten un mismo tratamiento.

Qué había antes:


Cada alternativa tenía que tener su propio case:

Qué añade JDK 25:
Ahora puedo combinar varias alternativas en una sola rama, usando comas:

 Esta mejora permite reducir duplicación y hace el switch más compacto.

2. Main minimalista en Java 25

Una de las mejoras que más se notan al empezar con pequeños programas en Java 25 es la posibilidad de escribir un main mucho más breve y natural. Tradicionalmente, el punto de entrada en Java era muy verboso, con definiciones largas y mucho código “ceremonial”. Ahora, gracias a la evolución del lenguaje, podemos reducirlo a lo esencial y hacer que el código sea más parecido al de otros lenguajes modernos.

Esto supone una gran ventaja para nuevos programadores, que ya no necesitan enfrentarse a tanta sintaxis obligatoria para imprimir un mensaje o recorrer una lista. El resultado es un estilo de programación más limpio, intuitivo y cercano a lo que hoy se espera al aprender un lenguaje actual.

En definitiva, el main minimalista de Java 25 facilita crear programas pequeños de forma rápida y expresiva, sin perder la solidez del ecosistema Java.

Qué había antes:

Qué añade JDK 25 (aprovechando estilo moderno):

Esto da como resultado un main minimalista, expresivo y alineado.

3. Creación de programa minimalista en JDK 25 (Java25)

Una de las barreras tradicionales para quienes empezaban con Java era la cantidad de “código obligatorio” que había que escribir incluso para ejecutar un programa mínimo. El clásico public static void main(String[] args) dentro de una clase pública hacía que un simple “Hola Mundo” pareciera mucho más complejo de lo necesario.

Con Java 25 esto cambia: ahora es posible escribir un main sin necesidad de declarar una clase ni un paquete. El compilador se encarga de generar la envoltura por nosotros, de modo que podemos centrarnos en la lógica sin distraernos con el “ceremonial” del lengu

Antes (Java clásico, con clase obligatoria)

Incluso para algo tan simple como imprimir texto había que declarar una clase pública, un método static y un array de argumentos.

Ahora (Java 25, main sin clase)

Con JDK 25 ya no es necesario pensar en clases ni en métodos static para empezar: podemos escribir directamente el código que queremos ejecutar, y Java se encarga del resto.

4. Nuevas utilidades de IO en JDK 25 (Java 25)

En Java 25, se introdujo la clase java.lang.IO como una mejora significativa para simplificar la interacción con la consola, especialmente en programas pequeños, scripts y entornos educativos. Esta clase proporciona métodos estáticos que facilitan la entrada y salida de datos sin necesidad de manejar directamente System.out o System.in.

Qué había antes:

Código verboso para poder imprimir una cadena por pantalla.

Qué añade JDK 25

Código menos  verboso para poder imprimir una cadena por pantalla.

Gracias a los nuevos métodos de IO en Java 25, leer y escribir cadenas se convierte en una tarea directa y expresiva. Lo que antes requería varias clases auxiliares y bloques de código extensos, ahora se resuelve con una sola llamada. Esta simplificación no solo reduce el boilerplate, sino que también acerca a Java a la experiencia de lenguajes modernos, facilitando el aprendizaje a nuevos desarrolladores y acelerando el trabajo con programas pequeños o ejemplos prácticos.

5. Scoped Values: el sucesor de ThreadLocal

ScopedValue (JEP 487) es la alternativa moderna a ThreadLocal pensada específicamente para trabajar con virtual threads. Su objetivo es ofrecer una forma segura y predecible de compartir datos entre métodos e hilos, evitando muchos de los problemas clásicos asociados a ThreadLocal.

Mientras que ThreadLocal es mutable, y no se integra bien con virtual threads, ScopedValue se diseñó con un enfoque distinto:

ScopedValue aporta un modelo más simple, seguro y adecuado para la era de los virtual threads, donde la concurrencia debe ser expresiva y sin sorpresas.

6. JEP 511: Module Import Declarations

JEP 511 introduce Module Import Declarations, que permite a los desarrolladores usar módulos para importar de manera sencilla todos los paquetes exportados por un módulo completo DEV CommunityOpenJDK.

¿Qué es?

Una nueva característica del lenguaje Java que permite importar todos los paquetes exportados por un módulo de una vez, simplificando la reutilización de librerías modulares sin requerir que el código importador esté en un módulo JEP 505: Structured Concurrency (Fifth Preview).

Qué había antes:

Para usar operaciones básicas de streams y collections necesitabas 4 imports específicos de diferentes paquetes (java.util, java.util.function, java.util.stream). Cada clase requería su import individual, creando boilerplate y fragmentando la gestión de dependencia.

Qué añade JDK 25

Un solo import modular (import module java.base) proporciona acceso a todas las clases de los 54 paquetes del módulo base de Java, incluyendo Map, Stream, Collectors y Function. El código funcional es idéntico, pero la gestión de imports se reduce en un 75%.

***Nota importante:  El compilador Java solo incluye en el bytecode las clases que realmente usas, no todas las que están disponibles por el import.

7. Bonus Track: JSpecify y el soporte en Spring

Su propósito es cubrir una carencia histórica del lenguaje: indicar de forma clara si un parámetro, atributo o valor de retorno puede ser null o no.

Hasta ahora cada framework o librería usaba su propio set de anotaciones (@Nullable, @NotNull, @NonNull, etc.), generando inconsistencias. JSpecify propone un lenguaje común para que herramientas (IDE, analizadores estáticos, librerías, frameworks) entiendan de forma uniforme las reglas de nullability.

Con JSpecify aparece un estándar abierto para manejar la “nullabilidad” de forma clara y consistente que nos va a permitir el tan ansiado antes de llegar e ejecución del temido “null pointer exception”.

En el ejemplo el ide nos va avisar del error y maven no va a dejar compilar el código si accedemos a llamar al método sin antes comprobar si es null.

Cuando realizamos la comprobación el código va a compilar correctamente.

JSpecify en Spring Framework 7

A partir de Spring Framework 7, el propio código base del framework adopta las anotaciones de JSpecify para:

Esto significa que la null-safety no es solo documentación, sino que está respaldada por análisis estático en el propio desarrollo de Spring.

Por esa razón, se recomienda que las librerías que dependen de Spring (ya sea del core o del resto del portfolio: Spring Boot, Reactor, Micrometer y proyectos de la comunidad) adopten también JSpecify. De este modo se garantiza un ecosistema coherente y seguro frente a NullPointerException, con un lenguaje común para expresar nullability en todo el stack.

Un futuro brillante para Java

JDK 25 demuestra la vitalidad inquebrantable del lenguaje. Lejos de ser un vestigio del pasado, Java se reinventa con cada versión, incorporando mejoras que no solo optimizan el rendimiento y la seguridad, sino que también simplifican el desarrollo y lo hacen más accesible. Desde la evolución de sus patrones de diseño hasta la gestión innovadora de la concurrencia, esta versión consolida a Java como un pilar fundamental en la ingeniería de software moderna..

Migrar a JDK 25 no es solo una actualización técnica; es una inversión estratégica que se traduce en mayor productividad, menos errores y una base tecnológica sólida, confirmando que Java es un lenguaje que se adapta, innova y lidera, desmintiendo cualquier idea de que es antiguo, y asegurando su lugar como una herramienta indispensable en el futuro de la programación.

Preguntas frecuentes sobre JDK 25 (Java 25)

¿Qué es JDK 25?

JDK 25 es la última versión de la plataforma Java Development Kit. Incorpora mejoras de productividad, seguridad y expresividad en el lenguaje, como un main minimalista, nuevas utilidades de IO, Scoped Values y la adopción oficial de JSpecify en Spring Framework 7.

¿Cuáles son las principales novedades de JDK 25?

Entre las novedades más destacadas de JDK 25 se incluyen:

¿Qué beneficios aporta JDK 25 a los desarrolladores?

Con JDK 25, los desarrolladores pueden escribir código más limpio, conciso y expresivo, con menos “boilerplate”. También mejora la concurrencia gracias a Scoped Values y simplifica la interacción con la consola. Además, el soporte de JSpecify reduce los temidos NullPointerException, aumentando la seguridad y robustez del software.

¿Qué es JSpecify y cómo se integra en JDK 25?

JSpecify es un estándar abierto para indicar nullability en Java. Permite documentar y validar si un parámetro, atributo o valor de retorno puede ser null.
En JDK 25, frameworks como Spring 7 lo adoptan oficialmente, garantizando un ecosistema nul

 ¿Merece la pena migrar a JDK 25?

Sí. Migrar a Java 25 no es solo una actualización técnica, sino una inversión estratégica. Permite aprovechar mejoras en productividad, reducir errores y mantener una base tecnológica sólida que garantiza compatibilidad futura y un desarrollo más ágil.

Salir de la versión móvil