Java fez grandes mudanças nos últimos anos, à medida que forças aparentemente díspares convergiram para tornar a plataforma mais fácil de usar. Novos recursos, como compilação automática e a palavra-chave var, reduzem o nível de uso do Java, tanto para iniciantes quanto para veteranos. Vamos dar uma olhada no que está acontecendo neste novo e mais amigável Java.

var

Talvez a coisa mais surpreendente sobre o Java moderno, pelo menos para os mais antigos, seja a presença de var apoiar. Uma das características que definem Java é que ele é fortemente tipado, mas var afrouxa um pouco isso. Dentro de um método, agora você pode definir uma referência usando var onde o compilador acompanhará o tipo para você.

Depois de muita preocupação sobre a sabedoria de introduzir esse recurso, os desenvolvedores Java de todos os lugares simplesmente o adotaram como se fosse a coisa mais óbvia de todos os tempos. Java não nos deixou sempre fazer isso?


var numbers = new ArrayList<Integer>();

Não, não aconteceu!

Compilação oculta

Esse novo recurso quase parece executar um arquivo de origem sem compilá-lo, mas o que está acontecendo nos bastidores é um pouco mais complicado. O arquivo .java ainda está compilado, mas o JEP 330 faz com que tudo fique oculto para você. Então agora você pode fazer:


$ java HelloWorld.java

Em vez de


$ javac HelloWorld.java
$ java HelloWorld

O executor compila o código-fonte na memória e executa a primeira classe principal que descobre.

O JEP 330 está limitado a um único arquivo de origem, mas espere, porque aí vem o JEP 458.

Compilar automaticamente vários arquivos de origem

JEP 458 se junta ao JEP 330 para permitir que os desenvolvedores executem vários arquivos de origem com compilação oculta. Quando uma fonte Java se refere a outra, o iniciador Java irá compilar a dependência na memória, carregá-la e fornecê-la. Resumindo, você pode executar programas inteiros de arquivos de origem inter-relacionados, desde que existam juntos no disco, sem uma etapa de compilação explícita.

Sou eu ou o Java está evoluindo para algo mais dinâmico? Isso é muito legal.

Um conjunto de ferramentas de construção melhor

A introdução do JEP 458 diz que visa:

Aprimore o inicializador de aplicativos Java para poder executar um programa fornecido como vários arquivos de código-fonte Java. Isso tornará a transição de programas pequenos para programas maiores mais gradual, permitindo que os desenvolvedores escolham se e quando se dar ao trabalho de configurar uma ferramenta de construção.

Isso diz em linguagem simples que Java está trabalhando para simplificar a vida dos desenvolvedores por meio de construções melhores. O JEP chega a dizer que “não é objetivo facilitar o uso de dependências de bibliotecas externas em programas de código-fonte”, embora “que poderá ser objecto de um futuro PEC” (itálico meu).

Entendo aqui que os desenvolvedores de Java estão trabalhando para tornar as ferramentas mais fáceis de usar, até mesmo no nível de dependência—finalmente! Maven ainda é minha ferramenta de construção preferida para projetos complexos, como tem sido há 15 anos, mas a ferramenta mostra sérios sinais de envelhecimento. (Um novo projeto de arquétipo no Maven escolhe o Java 1.7 como padrão!) Comparado ao NPM, o Maven é totalmente desajeitado; um verdadeiro impedimento para lançar projetos rapidamente, especialmente para iniciantes que precisam aprender a ferramenta de construção enquanto aprendem Java.

Um gerenciador de dependências ordenado pela plataforma pode ser a opção certa. Quando olho para o JEP 330 e o JEP 458 juntos, não vejo soluções fragmentadas para a usabilidade das ferramentas, mas a implementação cuidadosa de um conjunto de ferramentas integrado na plataforma. O que está surgindo é uma cadeia de ferramentas Java projetada para facilitar o início de um projeto e a adoção incremental de ferramentas mais sofisticadas conforme necessário.

JShell

Eu sei, o JShell já existe há muito tempo, mas vamos reconhecer como é bom ter um executor estilo REPL para Java. Lembre-se de usar o JShell para testar novas ideias rapidamente.

Servidor Web Simples

Um dia acordamos e Java tinha um servidor web de linha de comando. Você pode aprender tudo sobre o Simple Web Server do Java aqui.

A principal conclusão é: se você estiver usando Java 18 ou superior, sua instalação do JDK agora inclui uma maneira extremamente simples e fácil de servir arquivos. Como resultado, a plataforma Java é um pouco mais completa, integrada e completa. Já usei Python ou Node para necessidades básicas de serviço de arquivos; agora posso fazer tudo em Java.

Blocos de texto aninhados

Outro recurso que os desenvolvedores Java há muito invejavam em outras plataformas era uma maneira fácil de lidar com grandes blocos de texto no código. A JEP 378 traz os blocos de texto que procuramos:


String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;

Não sei sobre você, mas esse bloqueio me dá um suspiro de alívio.

Os blocos de texto também podem aninhar caracteres de aspas livremente:


String html = """
              <html>
                  <body>
                      <p>Hello, "This is a quote"</p>
                  </body>
              </html>
              """;

Gravar aulas

O produto do JEP 395, o record palavra-chave, permite criar um POJO (objeto Java simples e antigo) sem adicionar manualmente getters, setters, toString, equalse hashcode métodos como você faria normalmente. Quando você usa recorda plataforma adiciona todas essas sutilezas para você:


class Point {
    private final int x;
    private final int y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    int x() { return x; }
    int y() { return y; }

    public boolean equals(Object o) {
        if (!(o instanceof Point)) return false;
        Point other = (Point) o;
        return other.x == x && other.y == y;
    }

    public int hashCode() {
        return Objects.hash(x, y);
    }

    public String toString() {
        return String.format("Point(x=%d, y=%d)", x, y);
    }
}

Torna-se:


record Point(int x, int y) { }

O novo record as classes também permitem uma grande personalização, para que você possa adicionar o quanto quiser.

Interruptor novo e melhorado

Com JEP 361, Java switch a sintaxe tornou-se mais poderosa e fácil de usar. Isso aconteceu de duas maneiras: uma sintaxe mais limpa e a capacidade de usar switch como uma expressão e não apenas uma afirmação.

O switch agora torna possível usar uma sintaxe antiga e desajeitada como esta:


switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}

E transforme em algo assim:


switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

Igualmente incrível, você pode usá-lo como uma expressão para atribuição de variáveis ​​(que geralmente é tudo o que procuramos):


int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

Simultaneidade estruturada

Agora, a simultaneidade nunca será uma área de codificação despreocupada. Há algo inerentemente alucinante em trabalhar com vários threads. No entanto, a simultaneidade estruturada oferece possivelmente a maneira mais fácil de lidar com a simultaneidade no universo de codificação conhecido:


try (var scope = new StructuredTaskScope<Object>()) {
  for (int planetId : planetIds) {
    scope.fork(() -> getPlanet(planetId)); // fork a “process”
  } 
  scope.join();
} catch (Exception e){
  System.out.println("Error: " + e);
}

Quando combinada com os novos threads virtuais do Java, a simultaneidade estruturada é um superpoder entre as linguagens. Agora você pode usar simultaneidade facilmente em Java, sem gerando threads do sistema operacional e sem deixando construções de programação normais.

Conclusão

Os desenvolvedores de plataforma estão trabalhando em várias frentes para diminuir o nível de exigência dos desenvolvedores que trabalham em Java. Eles estão melhorando a vida cotidiana dos programadores que trabalham e tornando mais fácil começar a usar Java e experimentá-lo.

Esses esforços são especialmente impactantes naquele segmento peculiar do mundo dos desenvolvedores que chamarei de “prototipagem”, também conhecido como “brincadeira”. Quanto mais pudermos fazer para reduzir a distância entre pensar em tentar algo e realmente tentar, melhor.

É ótimo ver o Java em tão boa forma. Gosto da direção que está tomando e das pessoas que lideram esses esforços.