Annotation Interface NullUnmarked


@Documented @Retention(RUNTIME) @Target({PACKAGE,TYPE,METHOD,CONSTRUCTOR}) public @interface NullUnmarked
Indicates that the annotated element and the code transitively enclosed within it are in null-unmarked context: there, type usages generally have unspecified nullness unless explicitly annotated otherwise.

This annotation's purpose is to ease progressive migration of a large codebase. If some class or package can't be fully migrated yet, you can still make it null-marked by using this annotation on the portions that still need work. This practice is useful because it flips the default for new code added later, which is the most important code to analyze.

Once a codebase has been fully migrated it would be reasonable to ban use of this annotation.

For important information common to all four nullness annotations, see org.jspecify.annotations. To learn more about JSpecify, see jspecify.dev.

Null-marked and null-unmarked contexts

NullMarked puts enclosed code in null-marked context; this annotation puts it in null-unmarked context instead. These annotations work as an inclusion-exclusion pair: of the annotations of either type on all enclosing elements (methods, classes, etc.), only the nearest (most narrowly enclosing) one is in effect.

Otherwise, code is in null-unmarked context. This can happen in two ways: either it is more narrowly enclosed by a @NullUnmarked-annotated element than by any @NullMarked-annotated element, or neither annotation is present on any enclosing element. No distinction is made between these cases.

The effects of being null-marked are described in the Effects section of NullMarked.

Unspecified nullness

Within null-unmarked context, a type usage that is nullness-applicable but has no nullness annotation generally has unspecified nullness (Why?). This means we do not know whether it includes or excludes null as a value. In such a case, tools can vary widely in how strict or lenient their enforcement is, or might even be configurable.

For more, please see this more comprehensive discussion of unspecified nullness.

There is no way for an individual type usage within null-marked context to have unspecified nullness. (Why?)

Where it can be used

The information in the Where it can be used section of NullMarked applies as well to this annotation.