You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The documentation for @Nullable and @NotNull explicitly state the actions that these annotations apply to when used with methods, parameters, and variables/fields, but don't mention what it means when these annotations are used on a class.
An element annotated with Nullable claims null value is perfectly valid to return (for methods), pass to (parameters) or hold in (local variables and fields).
I tried annotating a class with @NotNull and @Nullable to see if IntelliJ's static analysis could provide hints about what's expected, but no warnings were generated for anything I did with it (beyond some "always-true" warnings for various combinations, but these were also generated without the class-level annotation). I've included the class below and documented my assumptions as a sanity-check.
I can think of two possible (likely) meanings:
Variables, fields, parameters. and returns declared as the annotated type should default to the annotated nullability
The fields, parameters, and/or return types within the annotated type should default to the annotated nullability
For the first option, I'm unsure what it would mean to apply @NotNull to a class given the strict constraints on using it with, for example, Map::get. There's no way a class can ever guarantee that it can or cannot be null everywhere it's used[*], since anyone can write MyClass myClass = null; (although that could generate a warning). However, if the strictness for using these annotations is more relaxed than with fields/methods/etc. and is more of a suggestion, then perhaps java.util.Optional should be annotated with @NotNull?
The second option also seems possible given my experience with other projects, but unlikely. Some class-level annotations are "distributed" into the class, such as Lombok's @Getter). However, I don't know of any annotation libraries that treat @Nullable/@NotNull this way, so I wouldn't assume that's how this annotation behaves. Plus, given the stance in #18, it seems this kind of functionality isn't desired (at least by JetBrains).
The official Javadoc for ElementType specifically mentions a hypothetical @NonNull annotation applied to a class via TYPE_USE, but I'm not clear on what it's trying to say.
The TYPE_USE constant includes class and interface declarations and type parameter declarations as a convenience for designers of type checkers which give semantics to annotation interfaces. For example, if the annotation interface NonNull is meta-annotated with @Target(ElementType.TYPE_USE), then @NonNull class C {...} could be treated by a type checker as indicating that all variables of class C are non-null, while still allowing variables of other classes to be non-null or not non-null based on whether @NonNull appears at the variable's declaration.
Does "variables of class C" refer to variables declared within class C, or variables with a type of C? I believe it's the latter, but IntelliJ's code analysis doesn't appear to use this information in this way (or at all).
In summary, what I'm requesting is:
Clarification of which of the scenarios in the example should be influenced by a type-level nullity annotation (plus any obvious ones I missed)
Updates to the documentation for @NotNull/@Nullable with the expected semantics (or lack thereof?) of annotating a type declaration with these annotations
If any of the scenarios should be influenced, I'd like IntelliJ's static analysis updated to report them.
[*] Ignoring Project Valalla, but from my understanding we would already be able to detect that a class is inline without an annotation
Tested using Java 8 & 11 with IntelliJ Ultimate 2021.1.2:
importjava.util.concurrent.ThreadLocalRandom;
importorg.jetbrains.annotations.NotNull;
importorg.jetbrains.annotations.Nullable;
@NotNullpublicclassExample {
privateIntegerfield1;
privateintfield2;
// Class-level @NotNull doesn't seem to influence fields, since this assignment doesn't produce a warningpublicvoidsetField1(@NullableIntegervalue) {
this.field1 = value;
}
// Class-level @NotNull/@Nullable don't seem to influence method parameters, since this (questionably) doesn't// produce a warning with either class annotation, nor with an absent class-level annotation.publicvoidsetField2(Integervalue) {
this.field2 = value;
}
protectedBooleanvalidate() {
Integervalue1 = this.field1;
Integervalue2 = this.field2;
// This is included solely to prevent an unavoidable constant conditions warning on the return, since// field2 is a primitive. I'm avoiding a suppression comment so that other warnings can still appear.if (ThreadLocalRandom.current().nextBoolean()) {
value2 = this.field1;
}
// Class-level @NotNull doesn't seem to influence method return types, since possibly returning null// here doesn't produce a warning when the class is annotated with @NotNull.return (value2 != null && value1 == null) ? null : true;
}
// Annotating the following method's parameter with @NotNull/@Nullable does not produce any warnings beyond// the null-check when the parameter is @NotNull, so a parameter of the annotated class's type doesn't appear// to default to the type's annotation, nor is a conflicting declaration considered invalid.// If nullity was expected to match the type's annotation, this would produce a warning if the parameter was// annotated with the opposite annotation.publicstaticbooleanvalidate(Exampleexample) {
// If parameter nullity was inherited from the parameter's type in the absence of an explicit// annotation this would produce a warning when the type was annotated @NotNull, even when// the parameter doesn't have an annotationif (example == null) {
returnfalse;
}
// Likewise, if the previous null check is removed and the class is annotated @Nullable, this would// produce a warning if nullity is inherited, but it does not, so @Nullable is also not inherited.Booleanvalue = example.validate();
if (value == null) {
returnfalse;
}
returnvalue;
}
// Annotating the following method's return type with @NotNull/@Nullable does not produce warnings beyond// returning null when the method is @NotNull, so a return type's nullity doesn't appear to default to the// type's annotation, nor is a conflicting declaration considered invalid.// If nullity was expected to match the class's annotation, this would produce a warning when the return// type was annotated the opposite annotation.publicstaticExamplecreate() {
Exampleex = newExample();
if (ex.validate() == Boolean.TRUE) {
returnex;
}
// If nullity for return types defaulted to the type's nullity, this would produce a warning when the// type was annotated @NotNull.returnnull;
}
}
The text was updated successfully, but these errors were encountered:
The documentation for
@Nullable
and@NotNull
explicitly state the actions that these annotations apply to when used with methods, parameters, and variables/fields, but don't mention what it means when these annotations are used on a class.I tried annotating a class with
@NotNull
and@Nullable
to see if IntelliJ's static analysis could provide hints about what's expected, but no warnings were generated for anything I did with it (beyond some "always-true" warnings for various combinations, but these were also generated without the class-level annotation). I've included the class below and documented my assumptions as a sanity-check.I can think of two possible (likely) meanings:
For the first option, I'm unsure what it would mean to apply
@NotNull
to a class given the strict constraints on using it with, for example,Map::get
. There's no way a class can ever guarantee that it can or cannot be null everywhere it's used[*], since anyone can writeMyClass myClass = null;
(although that could generate a warning). However, if the strictness for using these annotations is more relaxed than with fields/methods/etc. and is more of a suggestion, then perhapsjava.util.Optional
should be annotated with@NotNull
?The second option also seems possible given my experience with other projects, but unlikely. Some class-level annotations are "distributed" into the class, such as Lombok's
@Getter
). However, I don't know of any annotation libraries that treat@Nullable
/@NotNull
this way, so I wouldn't assume that's how this annotation behaves. Plus, given the stance in #18, it seems this kind of functionality isn't desired (at least by JetBrains).The official Javadoc for
ElementType
specifically mentions a hypothetical@NonNull
annotation applied to a class viaTYPE_USE
, but I'm not clear on what it's trying to say.Does "variables of class C" refer to variables declared within class C, or variables with a type of C? I believe it's the latter, but IntelliJ's code analysis doesn't appear to use this information in this way (or at all).
In summary, what I'm requesting is:
@NotNull
/@Nullable
with the expected semantics (or lack thereof?) of annotating a type declaration with these annotations[*] Ignoring Project Valalla, but from my understanding we would already be able to detect that a class is
inline
without an annotationTested using Java 8 & 11 with IntelliJ Ultimate 2021.1.2:
The text was updated successfully, but these errors were encountered: