Java saca una versión nueva cada seis meses, pero en las empresas casi todo el mundo usa una de las versiones de soporte extendido (LTS): 8, 11, 17, 21 y 25. Aquí tienes qué trajo cada una, con código que demuestra en qué versión llegó cada novedad, hasta cuándo tiene soporte, qué distribución del JDK instalar y qué se rompe al migrar desde Java 8. Si vas a empezar un proyecto hoy, la respuesta corta es Java 25.
Cómo se numeran las versiones
Desde Java 10 (2018) hay una versión nueva cada seis meses, en marzo y septiembre, con lo que esté listo en ese momento. La más reciente es Java 27, del 15 de septiembre de 2026. Cada cierto tiempo una de ellas es LTS (Long-Term Support): los distribuidores la mantienen con parches de seguridad durante años, mientras que las demás solo los reciben hasta que sale la siguiente, seis meses después. Desde Java 17 hay una LTS cada dos años: 17 (2021), 21 (2023) y 25 (2025); siguiendo ese ritmo, la siguiente sería Java 29, en septiembre de 2027.
- Java 8 (LTS)Marzo de 2014. Lambdas y streams: el gran cambio de estilo del lenguaje.
- Java 11 (LTS)25 de septiembre de 2018.
var, el cliente HTTP moderno y ejecutar un archivo sin compilarlo. - Java 17 (LTS)14 de septiembre de 2021. Records, bloques de texto,
switchcon flechas, clases selladas. - Java 21 (LTS)19 de septiembre de 2023. Hilos virtuales y pattern matching completo en
switch. - Java 25 (LTS)16 de septiembre de 2025. Programas de un archivo sin clase,
import moduley constructores más flexibles. - Java 2715 de septiembre de 2026. La última versión, sin soporte extendido.
Java 8: lambdas, streams y java.time
Es la versión que lo cambió todo, y por eso la que más tiempo se ha quedado en producción. Trajo las lambdas (funciones como valores), los streams para procesar colecciones encadenando operaciones, Optional y la API de fechas java.time, que sustituyó al viejo y confuso Date.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Java8 {
public static void main(String[] args) {
List<String> nombres = Arrays.asList("Ana", "Luis", "María", "Iker");
List<String> largos = nombres.stream()
.filter(n -> n.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(largos);
}
}salida[LUIS, MARÍA, IKER]
Java 11: var, HttpClient y archivos que se ejecutan solos
Entre la 9 y la 11 llegaron var para no repetir el tipo de las variables locales (Java 10), el cliente HTTP moderno java.net.http (que sustituye a HttpURLConnection), métodos útiles en String (isBlank, strip, lines, repeat) y la posibilidad de ejecutar un programa de un solo archivo con java Programa.java, sin compilarlo antes. También llegó el sistema de módulos (Java 9).
public class Java11 {
public static void main(String[] args) {
var texto = " hola ";
System.out.println("[" + texto.strip() + "]");
System.out.println("-".repeat(10));
System.out.println(" ".isBlank());
"uno\ndos\ntres".lines().forEach(System.out::println);
}
}salida[hola] ---------- true uno dos tres
javac --release 8Java11.java:4: error: cannot find symbol symbol: class var
Java 17: records, bloques de texto y clases selladas
La LTS que más ha cambiado la forma de escribir Java en el día a día. Los records (Java 16) definen en una línea una clase de datos con constructor, equals, hashCode y toString; los bloques de texto (15) escriben texto de varias líneas sin \n ni concatenaciones; el switch con flechas (14) devuelve valores y no cae al siguiente caso; instanceof declara la variable de una vez (16); y las clases selladas (17) dicen exactamente qué clases pueden heredar de otra. De regalo, los NullPointerException dicen por fin qué era null.
public class Java17 {
sealed interface Figura permits Circulo, Cuadrado {}
record Circulo(double radio) implements Figura {}
record Cuadrado(double lado) implements Figura {}
static String describir(Object o) {
if (o instanceof Circulo c) return "círculo de radio " + c.radio();
return "otra cosa";
}
public static void main(String[] args) {
Figura f = new Circulo(2);
System.out.println(f);
System.out.println(describir(f));
String json = """
{"lenguaje": "Java", "version": 17}
""";
System.out.print(json);
int dia = 6;
System.out.println(switch (dia) { case 6, 7 -> "fin de semana"; default -> "entre semana"; });
}
}salidaCirculo[radio=2.0]
círculo de radio 2.0
{"lenguaje": "Java", "version": 17}
fin de semanajavac --release 11Java17.java:3: error: sealed classes are not supported in -source 11
Java 21: hilos virtuales y pattern matching en switch
La estrella de Java 21 son los hilos virtuales: hilos ligerísimos que gestiona la JVM, de los que se pueden lanzar millones, ideales para servidores que pasan el tiempo esperando a la red o a la base de datos (tienes un ejemplo completo en tareas en paralelo con hilos virtuales). También completó el pattern matching: un switch puede distinguir por tipo y desarmar records, y el compilador comprueba que no falte ningún caso de una interfaz sellada. Y las colecciones con orden ganaron getFirst(), getLast() y reversed().
import java.util.List;
public class Java21 {
sealed interface Figura permits Circulo, Rectangulo {}
record Circulo(double radio) implements Figura {}
record Rectangulo(double ancho, double alto) implements Figura {}
static double area(Figura f) {
return switch (f) {
case Circulo(double r) -> Math.PI * r * r;
case Rectangulo(double a, double h) -> a * h;
};
}
public static void main(String[] args) throws Exception {
System.out.printf("%.2f%n", area(new Circulo(1)));
System.out.println(area(new Rectangulo(3, 4)));
List<String> dias = List.of("lunes", "martes", "miércoles");
System.out.println(dias.getLast() + " " + dias.reversed());
Thread t = Thread.ofVirtual().start(() -> System.out.println("hola desde un hilo virtual"));
t.join();
}
}salida3.14 12.0 miércoles [miércoles, martes, lunes] hola desde un hilo virtual
javac --release 17Java21.java:11: error: patterns in switch statements are not supported in -source 17
Java 25: Java sin ceremonia
Java 25 trae 18 mejoras (JEP). Las que más se notan al escribir código:
- Archivos compactos y
mainde instancia (JEP 512): un programa puede ser solo unvoid main(), sin clase nipublic static, y la nueva claseIOimprime y lee de la consola. Es lo que usan los ejemplos nuevos de decodigo.com. import module(JEP 511): importa de una vez todos los paquetes de un módulo, comojava.base.- Constructores flexibles (JEP 513): se puede validar y preparar datos antes de llamar a
super(...). - Scoped values (JEP 506): datos compartidos con los métodos que se llaman, más seguros y ligeros que
ThreadLocal, pensados para los hilos virtuales. - Por dentro: cabeceras de objeto compactas (JEP 519), que ahorran memoria si se activan con
-XX:+UseCompactObjectHeaders, y mejoras en el arranque anticipado (AOT, JEP 514 y 515). Se eliminó la versión para procesadores x86 de 32 bits (JEP 503).
import module java.base;
class Persona {
final String nombre;
Persona(String nombre) {
if (nombre.isBlank()) throw new IllegalArgumentException("sin nombre");
this.nombre = nombre.strip();
super();
}
}
void main() {
List<String> lenguajes = List.of("Java", "Kotlin", "Scala");
IO.println("Lenguajes de la JVM: " + String.join(", ", lenguajes));
IO.println("Hola, " + new Persona(" Ana ").nombre);
}salidaLenguajes de la JVM: Java, Kotlin, Scala Hola, Ana
javac --release 21Java25.java:2: error: module imports are not supported in -source 21
Fíjate en todo lo que falta: no hay public class, ni public static void main(String[] args), ni import java.util.List (lo trae import module java.base), y el constructor valida el nombre antes de super(), algo prohibido hasta Java 24.
Hasta cuándo tiene soporte cada versión
El soporte depende de quién te da el JDK. Estas son las fechas de Eclipse Temurin, la distribución gratuita y de código abierto más usada, según su página de soporte (comprobada el 6 de noviembre de 2026):
- Java 8Al menos hasta diciembre de 2030.
- Java 11Al menos hasta octubre de 2027.
- Java 17Al menos hasta octubre de 2027.
- Java 21Al menos hasta diciembre de 2029.
- Java 25Al menos hasta septiembre de 2031.
Las versiones que no son LTS (22, 23, 24, 26, 27…) dejan de recibir parches en cuanto sale la siguiente. Úsalas para probar novedades, no en producción.
Qué JDK instalar
Java es un estándar con una implementación abierta, OpenJDK, que varias empresas compilan y distribuyen. Todas pasan las mismas pruebas de compatibilidad y el código se comporta igual; cambian el soporte, las plataformas y la licencia:
- Eclipse TemurinDe la fundación Eclipse (proyecto Adoptium). Gratuito, para Windows, Mac y Linux. Es el que usamos para probar todo el código de decodigo.com, y la opción por omisión razonable.
- Amazon CorrettoGratuito, con parches de Amazon. Natural si tu aplicación corre en AWS.
- Microsoft Build of OpenJDKGratuito. El que usa Azure.
- Oracle JDKEl de Oracle. Sus condiciones de licencia han cambiado varias veces: léelas antes de usarlo en una empresa.
Para ver qué versión tienes instalada:
java -version (primera línea, en el contenedor de pruebas)openjdk version "25.0.5" 2026-10-20 LTS
Migrar desde Java 8: lo que se rompe
El código de Java casi siempre sigue compilando en versiones nuevas: la compatibilidad hacia atrás es una obsesión del lenguaje. Pero entre la 8 y la 25 se quitaron cosas, y estas son las que más aparecen en una migración:
import javax.xml.bind.JAXBContext;
public class SinJaxb {
public static void main(String[] args) throws Exception {
JAXBContext ctx = JAXBContext.newInstance(String.class);
}
}javacSinJaxb.java:2: error: package javax.xml.bind does not exist
- Java EE ya no viene incluido (desde Java 11): JAXB (
javax.xml.bind), JAX-WS, CORBA yjavax.annotationse quitaron del JDK. Se añaden como dependencias de Maven o Gradle, ahora con el paquetejakarta.*. - Encapsulamiento fuerte (desde Java 17): las bibliotecas que tocaban las tripas del JDK por reflexión fallan con
InaccessibleObjectException. La solución es actualizar la biblioteca; como parche,--add-opens. - El Security Manager no funciona (desde Java 24, JEP 486). Si tu aplicación dependía de él, hay que rediseñar esa parte.
- Nada de 32 bits en x86 (Java 25, JEP 503).
- Actualiza también las herramientas: Maven, Gradle, Lombok, Mockito y Spring tienen versiones mínimas para cada JDK; un Lombok o un Mockito viejos son la causa más común de errores raros al compilar tras el cambio.
El camino recomendado es saltar directamente a la LTS más reciente, compilar, arreglar lo que falle y pasar las pruebas. Si vienes de Java 8, el artículo Java 8 frente a Java 21 compara el mismo código escrito en las dos épocas.
Cada programa de esta página se ejecutó con Java 25 LTS (Eclipse Temurin). Los de Java 11 a 25 se compilaron además con --release igual a la versión que los introdujo, y se comprobó que no compilan con la LTS anterior (el javac de Java 25 ya no acepta --release 7, así que el de Java 8 no tiene esa prueba); los mensajes de error son los de esa compilación. Fechas de lanzamiento: openjdk.org; soporte: adoptium.net.
