Principais mudanças no Java nas versões LTS 8 a 25

Foto do autor Nelio Alves
Nelio Alves
Compartilhar
Compartilhar no LinkedInCompartilhar no FacebookCompartilhar no XCompartilhar no WhatsApp
Imagem banner do post

O Java evoluiu profundamente nos últimos anos. Quem parou no Java 8 costuma se surpreender com a quantidade de melhorias em linguagem, performance, APIs e modelo de releases. Neste conteúdo, apresentamos uma visão geral das versões do Java e percorremos as principais mudanças introduzidas em cada versão LTS, da 8 até a 25.

Entendendo as versões do Java

Desde 2017, o Java adotou um ciclo de lançamentos previsível, com novas versões a cada seis meses. Essas versões se dividem em dois tipos.

Versões não LTS

As versões não LTS são lançadas a cada seis meses e recebem atualizações por um período curto. Elas funcionam como um laboratório para novas funcionalidades, permitindo que a comunidade teste recursos antes de sua consolidação. Normalmente, não são adotadas em produção corporativa.

Versões LTS (Long-Term Support)

As versões LTS são lançadas aproximadamente a cada dois anos e recebem suporte prolongado, incluindo correções de bugs e atualizações de segurança. São as versões mais utilizadas em ambientes corporativos e em sistemas de longa vida. Exemplos clássicos são Java 8, 11, 17, 21 e 25.

Na prática, a maioria das empresas ignora as versões intermediárias e realiza atualizações diretamente de uma LTS para outra.

Java 8 (2014)

O Java 8 foi um divisor de águas e, por muitos anos, tornou-se o padrão dominante do mercado.

Entre as principais mudanças estão as expressões lambda, a Streams API, que introduziu um estilo funcional para processamento de coleções, os métodos default em interfaces, a classe Optional para lidar melhor com valores nulos e a nova API de data e hora (java.time).

O impacto prático dessas mudanças foi um código mais expressivo, menos verboso e com forte incentivo a um estilo funcional.

Copiar
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

class Java8Demo {

    interface Auditoria {
        default void log(String msg) {
            System.out.println("[AUDIT] " + msg);
        }
    }

    static Optional<String> primeiraPalavraLonga(List<String> palavras) {
        return palavras.stream()
                .map(String::trim)
                .filter(p -> p.length() >= 5)
                .findFirst();
    }

    public static void main(String[] args) {
        List<String> dados = Arrays.asList("  java ", "  spring ", "api", "cloud");

        List<String> upper = dados.stream()
                .map(s -> s.trim().toUpperCase())
                .collect(Collectors.toList());
        System.out.println(upper);

        String valor = primeiraPalavraLonga(dados)
                .orElse("(nenhuma palavra com 5+ chars)");
        System.out.println(valor);

        LocalDate hoje = LocalDate.now();
        System.out.println("Hoje: " + hoje);
    }
}

Java 11 (2018)

O Java 11 foi a primeira versão LTS após a adoção do novo ciclo de releases.

Essa versão consolidou diversas mudanças iniciadas no Java 9 e 10, como a remoção de módulos Java EE e CORBA do JDK, a introdução da nova API HTTP Client como padrão, melhorias na classe String, suporte ao uso de var em parâmetros lambda e a possibilidade de executar arquivos .java diretamente sem compilação explícita.

O impacto prático foi um JDK mais enxuto, moderno e alinhado com aplicações web e serviços HTTP.

Copiar
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;

class Java11Demo {
    public static void main(String[] args) throws Exception {

        String s = "  \n  Java 11  \n  ";
        System.out.println("isBlank? " + s.isBlank());
        System.out.println("lines: " + s.lines().toList());
        System.out.println("strip: '" + s.strip() + "'");

        List<String> nomes = List.of("ana", "bob", "carla");
        nomes.stream()
                .map((var n) -> n.toUpperCase())
                .forEach(System.out::println);

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create("https://example.com"))
                .GET()
                .build();

        HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println("Status: " + res.statusCode());
    }
}

Java 17 (2021)

O Java 17 é considerada uma das versões LTS mais importantes da história recente da linguagem.

Entre seus destaques estão os records, que reduzem drasticamente o boilerplate de classes de dados, as sealed classes, que permitem maior controle sobre hierarquias de herança, o pattern matching para instanceof e uma série de melhorias de performance e limpeza de APIs legadas.

O impacto prático foi uma grande evolução na modelagem de domínio e na legibilidade do código.

Copiar
record Money(String currency, long cents) {
    Money {
        if (currency == null || currency.isBlank()) {
            throw new IllegalArgumentException("currency");
        }
    }
}

sealed interface Payment permits Pix, CreditCard {
    Money amount();
}

record Pix(Money amount, String key) implements Payment {}
record CreditCard(Money amount, String last4) implements Payment {}

class Java17Demo {

    static String describe(Object obj) {
        if (obj instanceof Money m) {
            return m.currency() + " " + (m.cents() / 100.0);
        }
        return "(unknown)";
    }

    public static void main(String[] args) {
        Payment p = new Pix(new Money("BRL", 1299), "chave@pix");
        System.out.println(describe(p.amount()));
    }
}

Java 21 (2023)

O Java 21 consolidou recursos modernos que estiveram em incubação por várias versões.

O principal destaque é a introdução das virtual threads, que simplificam drasticamente o modelo de concorrência e permitem aplicações altamente escaláveis. Além disso, houve avanços importantes em pattern matching, melhorias no switch, novas coleções sequenciais e evoluções significativas no Garbage Collector.

Na prática, o Java passou a oferecer um modelo de concorrência mais simples, eficiente e adequado para aplicações modernas e cloud-native.

Copiar
import java.util.concurrent.Executors;

class Java21Demo {

    static void ioSimulada(int id) {
        try {
            Thread.sleep(50);
            System.out.println("OK " + id + " em " + Thread.currentThread());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    static String categoriaHttp(int status) {
        return switch (status) {
            case 200, 201, 204 -> "sucesso";
            case 400, 401, 403, 404 -> "cliente";
            case 500, 502, 503 -> "servidor";
            default -> "outro";
        };
    }

    public static void main(String[] args) {
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            for (int i = 1; i <= 10; i++) {
                int id = i;
                executor.submit(() -> ioSimulada(id));
            }
        }

        System.out.println(categoriaHttp(200));
        System.out.println(categoriaHttp(503));
    }
}

Java 25 (2025)

O Java 25 é a versão LTS mais recente e representa a maturidade da visão moderna da plataforma.

Essa versão traz refinamentos nas virtual threads, avanços adicionais em concorrência estruturada, melhorias contínuas em pattern matching e switch, além de ganhos relevantes de performance da JVM, especialmente em ambientes distribuídos e em nuvem.

O impacto prático é o fortalecimento do Java como uma plataforma moderna, escalável e preparada para sistemas de alta complexidade, sem abrir mão da compatibilidade com código legado.

Copiar
import java.time.Duration;
import java.util.concurrent.*;

record WorkResult(String jobId, boolean ok, Duration elapsed) {}

class Java25StyleDemo {

    static WorkResult runJob(String jobId) {
        long start = System.nanoTime();
        try {
            Thread.sleep(30);
            return new WorkResult(jobId, true,
                    Duration.ofNanos(System.nanoTime() - start));
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return new WorkResult(jobId, false,
                    Duration.ofNanos(System.nanoTime() - start));
        }
    }

    static String statusLine(WorkResult r) {
        return switch (r.ok()) {
            case true  -> "JOB " + r.jobId() + " OK em " + r.elapsed().toMillis() + "ms";
            case false -> "JOB " + r.jobId() + " FAIL em " + r.elapsed().toMillis() + "ms";
        };
    }

    public static void main(String[] args) throws Exception {
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            Future<WorkResult> a = exec.submit(() -> runJob("A"));
            Future<WorkResult> b = exec.submit(() -> runJob("B"));

            System.out.println(statusLine(a.get()));
            System.out.println(statusLine(b.get()));
        }
    }
}

Resumo das versões LTS do Java

VersãoAnoVisão Geral
Java 82014Introduziu programação funcional, streams e a nova API de datas, mudando profundamente o estilo de código Java.
Java 112018Consolidou o novo ciclo de releases, modernizou APIs e tornou o JDK mais enxuto.
Java 172021Evoluiu a modelagem de domínio com records e sealed classes, além de grandes ganhos de performance.
Java 212023Transformou o modelo de concorrência com virtual threads e consolidou recursos modernos.
Java 252025Refinou a concorrência e performance, reforçando o Java como plataforma moderna e cloud-native.
Foto do autor Nelio Alves
Nelio Alves
Desenvolvedor e Professor
Olá, meu nome é Nelio Alves. Sou graduado em Ciência da Computação e possuo mestrado e doutorado em Engenharia de Software pela Universidade Federal de Uberlândia. Trabalho como desenvolvedor e professor de programação há mais de 20 anos, e sou um dos educadores de tecnologia mais influentes da Internet com mais de 500 mil alunos online.