Manteniéndose al día con la tradición del ciclo de seis meses, después del lanzamiento de Java 13 el 17 de septiembre de 2019, está programado que Java 14, otra versión no LTS, se lance el 17 de marzo de 2020.
Características de Java 14
Aquí está la lista de características de Java 14:
- Switch Expressions (Estándar) – JEP 361
- Pattern Matching para instanceof (Vista previa) – JEP 305
- NullPointerExceptions útiles – JEP 358
- Records (Vista previa) – JEP 359
- Text Blocks (Segunda Vista previa) – JEP 368
- Paquete de herramientas (Incubadora) – JEP 343
- Asignación de memoria consciente de NUMA para G1 – JEP 345
- Transmisión de eventos de JFR – JEP 349
- Buffers de bytes asignados no volátiles – JEP 352
- ZGC en macOS – JEP 364
- ZGC en Windows – JEP 365
- API de acceso a memoria externa (Incubadora) – JEP 370
Configuración de instalación de Java 14 en Mac OS
- Para comenzar con Java 14, descarga el JDK desde aquí.
- Copia y extrae el archivo tar en el directorio
/Library/Java/JavaVirtualMachines
como se muestra a continuación:
$ cd /Library/Java/JavaVirtualMachines
$ sudo cp ~/Downloads/openjdk-14_osx-x64_bin.tar.gz /Library/Java/JavaVirtualMachines
$ sudo tar xzf openjdk-14_osx-x64_bin.tar.gz
$ sudo rm openjdk-14_osx-x64_bin.tar.gz
Una vez hecho esto, abre el archivo bash_profile
con cualquier editor de texto. En mi caso, estoy utilizando vim ~/.bash_profile
. Establece la ruta de Java 14 como JAVA_HOME, guarda los cambios y ejecuta source ~/.bash_profile
para reflejar los cambios.
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home
Finalmente, estás listo para compilar y ejecutar programas con Java 14. Utilizaremos JShell, una herramienta interactiva de línea de comandos REPL para probar rápidamente las nuevas características de Java 14.
Es importante tener en cuenta que muchas de las características lanzadas en Java 14 están en vista previa. Esto significa que aunque funcionan completamente en este momento, pueden modificarse en el futuro. Algunas podrían convertirse en estándar o simplemente eliminarse en los próximos ciclos de lanzamiento. Para probar las características en vista previa, es necesario establecer explícitamente --enable-preview
al ejecutar JShell o un programa Java, como se muestra a continuación:
jshell --enable-preview
javac --release 14 --enable-preview Author.java
En las próximas secciones, discutiremos algunas de las características del lenguaje y la JVM.
Lectura recomendada: Instalación de Java 14 en Linux
1. Expresiones de cambio (Switch Expressions)
Cambios en las expresiones de switch después de permanecer como una función de vista previa en las dos versiones anteriores, Java 12 y Java 13, finalmente han obtenido un estado permanente en Java 14.
- Java 12 introdujo la sintaxis lambda para las expresiones de switch, permitiendo así múltiples etiquetas de caso para la coincidencia de patrones y evitando caídas a través que llevan a un código verboso. También impuso casos exhaustivos, donde se generaría un error de compilación si no se cubren todos los casos de entrada.
- Java 13, en la segunda vista previa, introdujo declaraciones de
yield
en lugar debreak
para devolver valores desde una expresión.
Java 14 ha convertido finalmente estas características en estándar ahora.
String result = switch (day) {
case "M", "W", "F" -> "MWF";
case "T", "TH", "S" -> "TTS";
default -> {
if(day.isEmpty())
yield "Please insert a valid day.";
else
yield "Looks like a Sunday.";
}
};
System.out.println(result);

Nota: “Yield” no es una palabra clave nueva en Java. Solo se utiliza en expresiones de switch.
2. Coincidencia de patrones para instanceof (Vista previa)
Pregunta a cualquier desarrollador de Java que muestre su base de código y verás un buen uso de las condiciones instanceof
en todo el código. Específicamente, una verificación condicional de instanceof generalmente va seguida de una conversión de tipo.
Java 14 elimina esta verbosidad al hacer que la extracción condicional sea mucho más concisa.
Antes de Java 14:
if (obj instanceof Journaldev) {
Journaldev jd = (Journaldev) obj;
System.out.println(jd.getAuthor());
}
Java 14 en adelante:
if (obj instanceof Journaldev jd) {
System.out.println(jd.getAuthor());
}
En el código anterior, la instancia jd
solo se asignaría si obj
es del tipo Journaldev
. El alcance de la variable está limitado al bloque condicional solamente.
3. Helpful NullPointerExceptions
Las Excepciones de Puntero Nulo son una pesadilla para cualquier desarrollador. Anteriormente, hasta Java 13, era complicado depurar las infames NPEs. Los desarrolladores tenían que recurrir a otras herramientas de depuración o determinar manualmente la variable/método que era nula ya que la traza de pila solo mostraba el número de línea.
Antes de Java 14:
String name = jd.getBlog().getAuthor()
//Trayectoria de Pila
Exception in thread "main" java.lang.NullPointerException
at NullPointerExample.main(NullPointerExample.java:5)
Java 14 introdujo una nueva característica de la JVM que proporciona mejores conocimientos con una pila más descriptiva como se muestra a continuación:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Blog.getAuthor()" because the return value of "Journaldev.getBlog()" is null
at NullPointerExample.main(NullPointerExample.java:4)
Nota: La característica anterior no es una característica del lenguaje. Es una mejora en el entorno de ejecución.
4. Registros (Vista Previa)
A record is a data class that stores pure data. The idea behind introducing records is to quickly create simple and concise classes devoid of boilerplate code.
Normalmente, una clase en Java requeriría que implementes equals()
, hashCode()
, los métodos getters y setters. Aunque algunos IDE admiten la generación automática de tales clases, el código sigue siendo verboso. Con un record
, simplemente necesitas definir una clase de la siguiente manera.
record Author(){}
//o
record Author (String name, String topic) {}
El compilador de Java generará automáticamente un constructor, campos finales privados, accesores, métodos equals
/hashCode
y toString
. Los métodos getter generados automáticamente para la clase anterior son name()
y topic()
.
Para examinar el código generado, use javap Author
después de compilar el programa con javac
. La siguiente ilustración muestra la clase generada para record Author (String name, String topic) {}
:

La semántica de los registros es similar a las Clases de Datos en Kotlin
Además, podemos añadir campos, métodos y un constructor adicionales al registro de la siguiente manera:
record Author (int id, String name, String topic) {
static int followers;
public static String followerCount() {
return "Followers are "+ followers;
}
public String description(){
return "Author "+ name + " writes on "+ topic;
}
public Author{
if (id < 0) {
throw new IllegalArgumentException( "id must be greater than 0.");
}
}
}
El constructor adicional definido dentro del registro se llama constructor Compacto. No consiste en ningún parámetro y es solo una extensión del constructor canónico.
A compact constructor wouldn’t be generated as a separate constructor by the compiler. Instead, it is used for validation cases and would be invoked at the start of the main constructor.
Algunas cosas importantes a tener en cuenta sobre los Registros:
- A record can neither extend a class nor it can be extended by another class. It’s a final class.
- Los Registros no pueden ser abstractos
- Los Registros no pueden extender ninguna otra clase ni definir campos de instancia dentro del cuerpo. Los campos de instancia deben definirse solo en la descripción del estado
- Los campos declarados son privados y finales
- El cuerpo de un registro permite campos y métodos estáticos
Lectura recomendada: Registros de Java
4.1) Los valores dentro de los campos de referencia de un registro pueden ser mutados
Es importante tener en cuenta que para los campos definidos como objetos, solo la referencia es inmutable. Los valores subyacentes pueden ser modificados. La siguiente ilustración muestra un registro en el que se modifica el ArrayList. Como puedes ver, el valor se modifica cada vez que se cambia el ArrayList.

4.2) Los registros pueden implementar interfaces
El siguiente código muestra un ejemplo de implementación de una interfaz con registros:
record Author(String name, String topic) implements Information {
public String getFullName() {
return "Author "+ name + " writes on " + topic;
}
}
interface Information {
String getFullName();
}
Aquí está la salida del código anterior en acción en un JShell:

4.3) Los registros admiten múltiples constructores
Los registros permiten declarar múltiples constructores con o sin parámetros como se muestra a continuación:
record Author(String name, String topic) {
public Author() {
this("NA", "NA");
}
public Author(String name) {
this(name, "NA");
}
}
4.4) Los registros permiten modificar los métodos de acceso
Aunque los registros generan métodos de acceso públicos para los campos definidos en la descripción del estado, también te permiten redefinir los métodos de acceso en el cuerpo, como se muestra a continuación:
record Author(String name, String topic) {
public String name() {
return "This article was written by " + this.name;
}
}
4.5) Verificar el registro y sus componentes en tiempo de ejecución
Los registros nos proporcionan isRecord()
y getRecordComponents()
para verificar si la clase es un registro y también examinar sus campos y tipos. La siguiente ilustración muestra cómo se hace:

Si bien hemos agregado campos y métodos adicionales al registro en los ejemplos de código anteriores, asegúrate de no excederte. Los registros están diseñados como portadores de datos simples y si buscas implementar muchos métodos adicionales, es mejor volver a la clase normal.
5. Bloques de texto (Vista previa)
Los bloques de texto se introdujeron como una función de vista previa en Java 13 con el objetivo de permitir la fácil creación de literales de cadena de varias líneas. Es útil para crear fácilmente cadenas de HTML, JSON o consultas SQL.
En Java 14, los bloques de texto siguen en vista previa con algunas nuevas adiciones. Ahora podemos usar:
- La barra diagonal inversa para mostrar bloques de cadena de varias líneas con una apariencia agradable.
- El código \s se utiliza para considerar los espacios finales que, por defecto, son ignorados por el compilador. Preserva todos los espacios presentes antes de él.
String text = """
Did you know \
Java 14 \
has the most features among\
all non-LTS versions so far\
""";
String text2 = """
line1
line2 \s
line3
""";
String text3 = "line1\nline2 \nline3\n"
//text2 y text3 son iguales.
Referencias: OpenJDK 14
Source:
https://www.digitalocean.com/community/tutorials/java-14-features