basic model - jspecify/jspecify Wiki
We believe a basic understanding of JSpecify nullness should be enough for most users to handle most situations. That "Basic Model" goes like this:
- What Java does: Wherever references can flow through a program, a type is always specified in the code: a field type, method return type, etc. This type restricts which references are allowed through. Unfortunately, it always allows
- What JSpecify does: In most of these places, JSpecify lets us add a simple extra bit of related information: "and is
- What an analyzer does: A nullness analyzer uses that information in various smart ways to discover potential bugs: somewhere
nullcould flow to unallowed, or somewhere that could try to dereference
nulland trigger a
- What I do: I fix that code to handle the null case, or I adjust the annotations wherever the value came from (or wherever it's going), or I deem the finding to be safe and suppress it.
To make these changes, I simply think about where I do or don't want
null to be allowed to flow in my program, then follow some basic rules and recipes:
- I mark my classes/packages/modules with
- If a parameter is at least sometimes willing to accept
null, I mark it nullable.
- If a method will at least sometimes return
null, I mark its return type nullable.
- When using a generic class like
class List<T>, if I want to treat every unannotated appearance of
Tin that class as nullable at once, I write
- When writing a generic class like
class List<T>, if I want its users to have that
List<@Nullable Foo>option available, I write the incomprehensible incantation
class List<T extends @Nullable Object>.
If I hit a case where the Basic Model falls short, or I just crave a deeper understanding of what's really going on, it's time to read the type system model!