DEV Community

Paulo Porto
Paulo Porto

Posted on

Evolução da linguagem Java (parte 4)

Neste artigo damos continuidade à nossa análise histórica sobre os recursos que cada versão do Java trouxe para tornar o código mais limpo e simples para o desenvolvedor.

Se você caiu de paraquedas aqui e ainda não leu a primeira parte, clique aqui.

Java 15

O Java 15 consolidou Text Blocks e trouxe o preview de Sealed Classes.

Text Blocks

Os Text Blocks simplificam muito o uso de strings multilinha — sem necessidade de concatenar ou escapar quebras de linha e aspas.

// Before
String json = "{\n" +
              "  \"name\": \"Maria\",\n" +
              "  \"age\": 30\n" +
              "}";
System.out.println(json);

// Text Blocks
String json = """
    {
      "name": "Maria",
      "age": 30
    }
    """;
System.out.println(json);
Enter fullscreen mode Exit fullscreen mode

Java 16

O Java 16 consolidou Records e Pattern Matching para instanceof. Também trouxe o método toList() direto na Streams API, eliminando a necessidade de usar Collectors.

Records

Os Records foram criados para simplificar a criação de classes imutáveis de dados — aquelas que normalmente só têm atributos, construtor, getters, equals, hashCode e toString.

public record Person(String name, int age) {}
Enter fullscreen mode Exit fullscreen mode

O compilador gera automaticamente o Construtor, equals, hashCode e toString. Os atributos são final.

Person p = new Person("Maria", 30);
System.out.println(p.name()); // Maria
System.out.println(p); 
Enter fullscreen mode Exit fullscreen mode

Pattern Matching para instanceof

Este recurso se tornou oficial no Java 16.
Ele elimina a necessidade de fazer cast manual após o instanceof.

//Before
Object obj = "Hello Java";

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.toUpperCase());
}

// Pattern Matching for instanceof
Object obj = "Hello Java";

if (obj instanceof String s) {
    System.out.println(s.toUpperCase());
}
Enter fullscreen mode Exit fullscreen mode

Mais simples, mais seguro e mais legível.

toList() na Streams API.

O novo método toList() cria uma lista imutável, diferente do Collectors.toList(), que retorna uma lista mutável.

//Before
List<String> names = Stream.of("Ana", "Bruno", "Carlos")
.map(String::toUpperCase)
.collect(Collectors.toList());

System.out.println(names);

// Java 16
List<String> names = Stream.of("Ana", "Bruno", "Carlos")
.map(String::toUpperCase)
.toList();

System.out.println(names);
Enter fullscreen mode Exit fullscreen mode

Se tentar adicionar elementos à lista resultante, será lançada uma UnsupportedOperationException.

Java 17

O Java 17 consolidou as Sealed Classes e as Switch Expressions, e como preview o Pattern Matching switch.

Sealed Classes

As Sealed Classes permitem controlar explicitamente quais classes podem herdar de uma classe base ou implementar uma interface.

public sealed class Forma 
    permits Circulo, Retangulo, Triangulo {}

final class Circulo extends Forma {}
final class Retangulo extends Forma {}
final class Triangulo extends Forma {}
Enter fullscreen mode Exit fullscreen mode

Apenas as classes Circulo, Retangulo e Triangulo podem herdar de Forma.
Se alguém tentar criar class Hexagono extends Forma {}, o compilador retorna erro.
Além disso, subclasses devem ser final, sealed ou non-sealed, definindo se a hierarquia pode ou não continuar.

sealed class Animal permits Mamifero, Ave {}

final class Mamifero extends Animal {}
non-sealed class Ave extends Animal {}
Enter fullscreen mode Exit fullscreen mode

Switch Expressions

O novo switch pode retornar valores, usar lambda arrows (->) e ainda evita fall-through acidental.

int day = 2;

//Before
String dayName;

switch (day) {
    case 1:
        dayName = "Domingo";
        break;
    case 2:
        dayName = "Segunda";
        break;
    default:
        dayName = "Outro dia";
}
System.out.println(dayName);

//Switch Expressions
String dayName = switch (day) {
    case 1 -> "Domingo";
    case 2 -> "Segunda";
    default -> "Outro dia";
};

System.out.println(dayName);
Enter fullscreen mode Exit fullscreen mode

Java 18

O Java 18 não trouxe novidades de sintaxe, mas entregou outros avanços voltados à consistência do que à escrita de código em si.

Conclusão

Meus recursos favoritos dessas versões foram os Text Blocks, as Switch Expressions e o toList() na Streams API.
Os Text Blocks facilitaram muito a escrita de queries e strings longas, e as Switch Expressions economizam boas linhas de código no dia a dia.
O toList() é um método que uso bastante — mas é importante lembrar que ele cria uma lista imutável, o que pode ser um detalhe crítico quando se trabalha com enriquecimento de dados ou junção de coleções.
Gosto bastante dos Records como substitutos para a maioria dos DTOs/VOs, e estou animado para testá-los em conjunto com o OpenFeign.
Pattern Matching para instanceof éé bem interessante, embora eu ainda não tenha encontrado uma aplicação prática recente — o último projeto em que explorei bastante interfaces ainda estava em Java 8.
Já as Sealed Classes não me agradaram tanto.
Elas parecem proteger o código — mas de quem, afinal? De você mesmo? De outro colaborador?
Na prática, considero uma “proteção frágil”: um simples commit sem revisão e pronto, nada foi realmente protegido.

👉Concorda com a minha análise? Se lembrar de algum recurso relevante que não citei, compartilhe nos comentários.

Gostou deste artigo? Me siga e fique atento para a terceira parte, onde vamos explorar o que veio do Java 19 em diante.

Top comments (0)