Recursos do Java 14

Mantendo a tradição do ciclo de seis meses, após o lançamento do Java 13 em 17 de setembro de 2019, está programado o lançamento do Java 14, outra versão não-LTS, em 17 de março de 2020.

Recursos do Java 14

Aqui está a lista de recursos do Java 14:

  • Switch Expressions (Padrão) – JEP 361
  • Pattern Matching para instanceof (Prévia) – JEP 305
  • NullPointerExceptions úteis – JEP 358
  • Records (Prévia) – JEP 359
  • Text Blocks (Segunda Prévia) – JEP 368
  • Packaging Tool (Incubadora) – JEP 343
  • Alocação de Memória Consciente de NUMA para G1 – JEP 345
  • Transmissão de Eventos JFR – JEP 349
  • Buffers de Bytes Mapeados Não Voláteis – JEP 352
  • ZGC no macOS – JEP 364
  • ZGC no Windows – JEP 365
  • API de Acesso a Memória Externa (Incubadora) – JEP 370

Configuração de Instalação do Java 14 no Mac OS

  • Para começar com o Java 14, faça o download do JDK da aqui.
  • Copie e extraia o arquivo tar no diretório /Library/Java/JavaVirtualMachines conforme mostrado abaixo:
$ 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

Uma vez feito isso, abra o arquivo bash_profile usando qualquer editor de texto. Estou usando vim ~/.bash_profile. Defina o caminho do Java14 para JAVA_HOME, salve as alterações e faça um source ~/.bash_profile para refletir as alterações.

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home

Finalmente, você está pronto para compilar e executar programas usando Java 14. Estaremos usando JShell, uma ferramenta interativa de linha de comando REPL para testar rapidamente os novos recursos do Java 14.

É importante notar que muitos recursos lançados no Java 14 estão em prévia. Isso significa que, embora estejam totalmente funcionais agora, as coisas podem ser modificadas no futuro. Algumas podem se tornar padrão ou simplesmente ser removidas nos próximos ciclos de lançamento. Para testar recursos em prévia, você precisa definir explicitamente --enable-preview ao executar o JShell ou Programa Java conforme mostrado abaixo:

jshell --enable-preview

javac --release 14 --enable-preview Author.java

Nas próximas seções, vamos discutir alguns dos recursos de linguagem e JVM.

Leitura recomendada: Instalando o Java 14 no Linux

1. Expressões de Switch

As expressões switch, depois de permanecerem como uma funcionalidade de visualização nas duas últimas versões – Java 12 e Java 13, finalmente alcançaram status permanente no Java 14.

  • O Java 12 introduziu a sintaxe lambda para expressões switch, permitindo assim múltiplos rótulos de caso para correspondência de padrões, além de evitar quedas indesejadas, o que resultava em código verboso. Também impôs casos exaustivos, onde um erro de compilação seria gerado se todos os casos de entrada não fossem cobertos.
  • O Java 13, na segunda visualização, introduziu instruções yield em vez de break para retornar valores de uma expressão.

O Java 14 finalmente tornou esses recursos padrão agora.

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

Observação: “Yield” não é uma nova palavra-chave em Java. É simplesmente usada em expressões switch.

2. Correspondência de Padrões para instanceof (Visualização)

Pergunte a qualquer desenvolvedor Java para mostrar seu código e você verá um bom uso de condições instanceof em todo o código. Especificamente, uma verificação condicional de instanceof geralmente é seguida por uma conversão de tipo.

O Java 14 elimina essa verbosidade, tornando a extração condicional muito mais concisa.

Antes do Java 14:

if (obj instanceof Journaldev) {
  Journaldev jd = (Journaldev) obj;
  System.out.println(jd.getAuthor());
}

Java 14 em diante:

if (obj instanceof Journaldev jd) {
  System.out.println(jd.getAuthor());
}

No código acima, a instância jd seria atribuída apenas se obj for do tipo Journaldev. O escopo da variável é limitado ao bloco condicional apenas.

3. Helpful NullPointerExceptions

As Exceções de Ponteiro Nulo são um pesadelo para qualquer desenvolvedor. Anteriormente, até o Java 13, era complicado depurar as infames NPEs. Os desenvolvedores tinham que recorrer a outras ferramentas de depuração ou descobrir manualmente a variável/método que estava nula, já que o rastreamento de pilha só mostrava o número da linha.

Antes do Java 14:

String name = jd.getBlog().getAuthor()

//Rastreamento de pilha
Exception in thread "main" java.lang.NullPointerException
    at NullPointerExample.main(NullPointerExample.java:5)

O Java 14 introduziu um novo recurso da JVM que fornece melhores insights com um rastreamento mais descritivo, como mostrado abaixo:

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: O recurso acima não é um recurso da linguagem. É uma melhoria no ambiente de tempo de execução.

4. Registros (Visualização)

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, uma classe em Java exigiria que você implementasse equals(), hashCode(), os métodos getters e setters. Embora alguns IDEs suportem a geração automática de tais classes, o código ainda é verboso. Com um record, você precisa simplesmente definir uma classe da seguinte maneira.

record Author(){}
//ou
record Author (String name, String topic) {}

O compilador Java gerará automaticamente um construtor, campos privados finais, acessores, métodos equals/hashCode e toString. Os métodos getter gerados automaticamente para a classe acima são name() e topic().

Para examinar o código gerado, use javap Autor após compilar o programa usando javac. A seguinte ilustração mostra a classe gerada para record Autor (String nome, String tópico) {}:

Javap Records Java 14

A semântica dos Registros é similar às Classes de Dados em Kotlin

Além disso, podemos adicionar campos adicionais, métodos e construtor ao registro da seguinte maneira:

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.");
     }
   }
}

O construtor adicional definido dentro do registro é chamado de construtor Compacto. Ele não consiste em nenhum parâmetro e é apenas uma extensão do construtor 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.

Algumas coisas importantes a serem observadas sobre Registros:

  • A record can neither extend a class nor it can be extended by another class. It’s a final class.
  • Registros não podem ser abstratos
  • Registros não podem estender qualquer outra classe e não podem definir campos de instância dentro do corpo. Os campos de instância devem ser definidos apenas na descrição do estado
  • Os campos declarados são privados e finais
  • O corpo de um registro permite campos e métodos estáticos

Leitura recomendada: Registros Java

4.1) Os valores dentro dos campos de referência de um registro podem ser mutáveis

É importante notar que, para campos definidos como objetos, apenas a referência é imutável. Os valores subjacentes podem ser modificados. A ilustração a seguir mostra um registro no qual o ArrayList é modificado. Como você pode ver, o valor é modificado sempre que o ArrayList é alterado.

Java 14 Records Mutable Values For References

4.2) Registros podem implementar interfaces

O código a seguir mostra um exemplo de implementação de uma interface com registros:

record Author(String name, String topic) implements Information {
  public String getFullName() {
    return "Author "+ name + " writes on " + topic;
  }
}

interface Information {
  String getFullName();
}

Aqui está a saída do código acima em ação em um JShell:

Java 14 Records With Interface

4.3) Registros suportam vários construtores

Registros permitem a declaração de múltiplos construtores com ou sem parâmetros, conforme mostrado abaixo:

record Author(String name, String topic) {
  public Author() {

    this("NA", "NA");
  }

  public Author(String name) {

    this(name, "NA");
  }
}

4.4) Os Registros Permitem Modificar Métodos de Acesso

Mesmo que os registros gerem métodos de acesso público para os campos definidos na descrição do estado, eles também permitem que você redefina os métodos de acesso no corpo, como mostrado abaixo:

record Author(String name, String topic) {
  public String name() {
        return "This article was written by " + this.name;
    }
}

4.5) Verificar Registro e seus Componentes em Tempo de Execução

Os registros nos fornecem isRecord() e getRecordComponents() para verificar se a classe é um registro e também examinar seus campos e tipos. A ilustração a seguir mostra como isso é feito:

Java 14 Records Runtime Check

Mesmo que tenhamos adicionado campos e métodos adicionais ao registro nos exemplos de código acima, certifique-se de não exagerar. Registros são projetados como transportadores de dados simples e se você estiver procurando implementar muitos métodos adicionais, é melhor voltar ao uso normal de classes.

5. Blocos de Texto (Prévia)

Os Blocos de Texto foram introduzidos como uma funcionalidade de prévia no Java 13 com o objetivo de permitir a fácil criação de literais de string multilinha. É útil na criação fácil de strings HTML, JSON ou consultas SQL.

No Java 14, os Blocos de Texto ainda estão em prévia com algumas adições. Agora podemos usar:

  • Barra invertida para exibir blocos de string multilinha com uma aparência agradável.
  • \s é usado para considerar espaços finais que, por padrão, são ignorados pelo compilador. Ele preserva todos os espaços presentes antes dele.
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"

// texto2 e texto3 são iguais.

Referências: OpenJDK 14

Source:
https://www.digitalocean.com/community/tutorials/java-14-features