Características de Java 14

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 de break 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);
Java 14 Switch Expressions

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) {}:

Javap Records Java 14

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.

Java 14 Records Mutable Values For References

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:

Java 14 Records With Interface

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:

Java 14 Records Runtime Check

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