Skip to content

Use JSpecify Annotations for Nullability #19

@philliplbryant

Description

@philliplbryant

Proposal: Use JSpecify annotations for nullability instead of Jakarta annotations

Summary

This issue proposes migrating the library’s nullability annotations from Jakarta (jakarta.annotation.*) to JSpecify (org.jspecify.annotations.*).

JSpecify is designed specifically for expressing Java nullness in a way that works consistently across IDEs, static analyzers, and JVM languages such as Kotlin. Adopting JSpecify would improve the clarity and portability of the library’s nullability contracts, particularly for downstream consumers.


Motivation

1. Clearer nullness semantics for libraries

JSpecify defines a precise model for nullness semantics, whereas Jakarta nullability annotations were not originally designed to provide a standardized interpretation across tools.

In practice, Jakarta annotations may be interpreted differently by IDEs, static analyzers, or frameworks. JSpecify instead aims to provide a consistent, tool-agnostic definition of nullness contracts.

JSpecify also fully supports type-use annotations, which allows nullability to be expressed within generic types:

List<@Nullable String>
Map<String, @Nullable Integer>

2. Better interoperability with Kotlin

Kotlin increasingly recognizes JSpecify annotations when determining nullability of Java APIs.

Using JSpecify improves Kotlin callers’ experience by producing more accurate Kotlin types (nullable vs non-nullable) when interacting with this library.


3. Improved static analysis support

Modern static analysis tools (for example Error Prone + NullAway, Checker Framework, etc.) increasingly support JSpecify as the canonical nullness annotation set.

This allows projects to enforce nullness correctness in CI pipelines without tying the library to a specific IDE or vendor annotation set.


4. Library-friendly defaulting model

JSpecify supports a clear default model via @NullMarked, where types are non-null by default and only exceptions require explicit @Nullable.

Example:

import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
package com.example.library;

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions