I am getting this error in both SonarQube Community Server version v25.1.0.102122 and SonarQube for IDE in IntelliJ (sample code bellow only in SonarQube for IDE as it is not in a project managed by our SonarQube server).
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
public class S2637Test {
List<@NonNull String> field;
// "field" is marked "@NonNull" but is not initialized in this constructor
public S2637Test() {
// nothing to do
}
}
The annotation in the generic type of the list seems to be throwing off the analysis. If I add a Nullable annotation to field it works. If I remove the NonNull annotation in the generic type the error disappears as well. I do not have a default NonNull rule in my code, which seems to be confirmed by the test without annotations.
The issue seems to be linked the annotations in generics as it affects multiple rules. I have another example where rule S2589 is affected. Again both in SonarQube Server and IDE. Both with connected projects and unconnected projects.
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
public class S2589Test {
public void test(Map<Long, List<@NonNull String>> testMap) {
List<@NonNull String> list = testMap.get(Long.valueOf(17));
// Remove this expression which always evaluates to "true"
if (list != null) {
System.err.println("[S2589Test] test - " + list.toString());
}
}
}
Again removing the NonNull annotation in the method declaration makes the error disappear.
I’m confused. You’re reporting a false positive when a non-null field is not initialized? I.e. when it’s left null? I don’t understand what’s “false” about that.
SonarQube is complaining that the condition “list != null” is always true. This is an item that has been retrieved from a Map using a random key (in this code sample I arbitrarily chose the value 17). There is no way SonarQube can know if that element is present in the Map or not (the Map could be completely empty).
The problem is that the NonNull annotation from the generic type of the List (NonNull String) is being applied to the List declaration.
SonarQube is behaving as if the method signature was (which in this case would be a very bad type signature) :
public void test(Map<Long, @NonNull List<String>> testMap) {
}
If the NonNull annotation is removed, is replaced by Nullable or if the Nullable annotation is added to the List itself then the message from SonarQube disappears.
I have many other cases where this is happening, breaking all sorts of rules. But there does not seem to be any point flooding the forum with all the cases I can find.
Very sorry I am causing confusion. I will get back to the original question.
field is a List that has no annotations on itself. The fact that there is a generic type of NonNull String should not affect the nullability of the field itself.
However, SonarQube is complaining that the constructor is not initializing “field” that is marked NonNull. The field in not marked as NonNull is is not marked at all.
If the field declaration is changed to :
List<String> field;
or
List<@Nullable String> field;
then the warning goes away.
But the annotation on the generic type should have no effect on whether the field is initialized in the constructor or not. The annotation on the String generic type seems to leak out onto the List.
Again, I am very sorry for posting about both issues in the same ticket, but in both cases the annotation from the generic type seems to leak out into the field.
This is a field that is not annotated either null or non null. The NonNull annotation on this line signifies that the list may only contain non null Strings.
SonarQube should treat this exactly the same way as :
List<String> field;
If I put that code in my test case, I get no message saying that field has not been initialized. Which is correct. However I want to specify that the list can only contain NonNull Strings.
Instead it is being treated as if the line was :
@NonNull List<String> field;
Since moving to version 25.X I am seeing lots of cases (several thousand in our code base) of NonNull (or Nullable) annotations in the generic type of a field having an impact on the field itself.
If you look at the second example I posted in this ticket. The same problem happens. The NonNull annotation from the generic type (NonNull String) affects the map value type List. Causing an error in the analysis of the call to the Map.get() method.