Null-Safety no Java com JSpecify

Por Gaspar Barancelli Junior em 04 de janeiro de 2025
Imagem ilustrativa sobre o post Null-Safety no Java com JSpecify

Cada vez mais, bibliotecas e frameworks do ecossistema Java estão adotando anotações de null-safety para prevenir a temida NullPointerException em tempo de execução. Uma das principais iniciativas nesse sentido é o JSpecify, que vem sendo abraçado por diversos projetos — incluindo o próprio Spring Framework.

Neste post, falaremos sobre o que é o JSpecify, como ele vem sendo adotado pelo Spring Framework e quais são os benefícios em utilizá-lo em projetos Java. Vamos citar também o NullAway, um projeto open source da Uber, e como outras ferramentas de análise estática, como o SonarQube (a partir da versão 8.5), podem ajudar você a manter seu código livre de problemas de null-safety.

O que é o JSpecify?

O JSpecify é um esforço da comunidade para padronizar anotações que descrevem a nullabilidade de variáveis, parâmetros e retornos de métodos em Java. Até então, muitas bibliotecas criavam suas próprias anotações (por exemplo, @Nullable ou @NonNull) ou dependiam de especificações como JSR 305 que foi descontinuado. Com o JSpecify, a ideia é oferecer um padrão unificado que facilite:

  1. Documentação: Tornar explícito se um método aceita, retorna ou pode retornar null.

  2. Ferramentas de Análise: Permitir que ferramentas como NullAway, SonarQube, IntelliJ IDEA e Eclipse compreendam e validem as condições de nullability declaradas.

  3. Integração com Outras Linguagens: Em Kotlin, por exemplo, as anotações JSpecify são traduzidas automaticamente para o modelo de null-safety da linguagem.

Para conhecer a iniciativa, visite o site oficial: JSpecify

Adoção pelo Spring Framework

Com o lançamento do Spring Framework 7, a equipe do projeto decidiu substituir gradualmente as anotações de null-safety existentes (como @Nullable e @NonNull de org.springframework.lang) pelas novas anotações do JSpecify. Isso significa que o próprio Spring passa a:

  1. Expor APIs com Anotações JSpecify: Tornando explícita a possibilidade de parâmetros e retornos serem nulos ou não.

  2. Validar Consistência: Durante a fase de build, o Spring utiliza o NullAway para garantir que suas próprias declarações de nullability estejam corretas.

Você pode conferir mais detalhes na documentação oficial do Spring: Null-Safety no Spring Framework 7

Por que Usar JSpecify no Seu Projeto?

  1. Menos NullPointerException em Produção Ao deixar claro onde null é permitido (ou não) no seu código, as ferramentas podem apontar problemas antes do deploy. Isso evita muito retrabalho e dores de cabeça.

  2. Melhor Documentação As anotações servem como documentação viva: quando um novo desenvolvedor (ou seu “eu do futuro”) lê o código, já sabe onde null pode aparecer ou não.

  3. Maior Interoperabilidade Com um padrão unificado, fica mais simples integrar bibliotecas de terceiros que também adotem o JSpecify, evitando confusões de anotações.

  4. Integração com Análise Estática Ferramentas como NullAway e SonarQube (versão 8.5+ ver detalhes) podem analisar seu código e mostrar as violações de null-safety.

NullAway: Análise Estática Open Source da Uber

O NullAway é um plugin open source para o compilador Java (Javac), criado pela Uber, que valida o uso das anotações de nullability no seu projeto. Ele funciona de forma semelhante a um linter, rejeitando builds em que haja inconsistências — por exemplo, se você estiver chamando um método que não aceita null e, mesmo assim, passa null para ele.

Por ser integrado ao processo de compilação, o NullAway é rápido e pode ser configurado em Maven ou Gradle com poucos passos, como veremos a seguir.

SonarQube e a Validação de Null-Safety

O SonarQube 8.5 passou a incluir verificações para anotações de nullability (inspiradas, inclusive, pelo JSpecify). Ao analisar o código, o SonarQube consegue apontar potenciais violações e fornecer relatórios gerenciais e históricos sobre a qualidade do código, ajudando a manter um padrão de qualidade na equipe de desenvolvimento.

Exemplo de Código Usando JSpecify

Abaixo, um exemplo simples de como anotar uma classe com JSpecify, considerando o uso de @NullMarked em nível de pacote (para que tudo seja não-nulo por padrão) e a anotação @Nullable onde necessário.

package-info.java

@NullMarked
package com.example.demo;

import org.jspecify.annotations.NullMarked;

MyService.java

package com.example.demo;

import org.jspecify.annotations.Nullable;

public class MyService {

    // Campo que pode ser nulo
    private @Nullable String configValue;

    // Construtor que não aceita nulo (não precisa anotar pois default é NonNull)
    public MyService(String configValue) {
        this.configValue = configValue;
    }

    // Exemplo de getter que pode retornar nulo
    public @Nullable String getConfigValue() {
        return this.configValue;
    }

    // Método que não aceita nulo como parâmetro (sem anotação, pois é NonNull por padrão)
    public void doSomethingImportant(String value) {
        // ...
    }
}

Repare que, por padrão (@NullMarked), os tipos são considerados não-nulos. Por isso, usamos @Nullable apenas quando realmente queremos permitir null.

Conclusão

Adotar o JSpecify traz clareza ao seu código sobre a possibilidade de ocorrência de null em variáveis, parâmetros e retornos de métodos. Com esse padrão:

  • O Spring Framework (versão 7 em diante) já está trazendo anotações JSpecify para suas APIs.

  • Ferramentas de análise estática como NullAway (open source da Uber) e SonarQube (a partir da versão 8.5) dão suporte a essas anotações, garantindo que o seu projeto seja consistente em relação à nullabilidade.

  • Outras linguagens da JVM, como Kotlin, conseguem mapear automaticamente essas anotações, reforçando a segurança em todo o ecossistema.

Se você quer um código mais robusto, bem documentado e fácil de integrar com as melhores práticas de análise estática, migrar para o JSpecify (e configurar ferramentas como o NullAway) deve estar no topo das suas prioridades. Experimente e veja como isso reduz (ou até elimina) os problemas de NullPointerException em produção!

// Compartilhe esse Post

💫
🔥 NOVO APP

Domine o Inglês em 30 dias!

Inteligência Artificial + Repetição Espaçada • Método cientificamente comprovado

✅ Grátis para começar 🚀 Resultados rápidos
×