Hello I have parent class with argument with nullable annotation.
class Parent {
@Nullable
String name;
Parent(@Nullable Strign name) {
this.name = name;
}
Driver createDriver() {
return new CommonDriver(name);
}
}
I have multiple children classes, for most of them, the "name" argument can be null, but there are some for which it cannot.
class ChildC extends Parent {
ChildC(@NotNull String name){
super(name);
}
@Override
Driver createDriver() {
return new ChildCDriver(name);
}
}
and now I have issue (code inspection from intelliJ) inside ChildCDriver where name is @NotNull
Can this be solved somehow ?
This is reasonable code, but IntelliJ is not powerful enough to prove that the code is correct. You need to suppress the warning. Click on the line, press Alt+Enter
, and find "Suppress" in that menu or a submenu.
The Nullness Checker can verify your code. The complete code appears below. The @FieldInvariant
annotation expresses that the field has a more precise type in the subclass.
Without the @FieldInvariant
annotation, the Nullness Checker issues this warning on line 27:
error: [argument.type.incompatible] incompatible types in argument.
return new ChildCDriver(name);
^
found : @Initialized @Nullable String
required: @Initialized @NonNull String
With the @FieldInvariant
annotation, the Nullness Checker proves the code is correct.
The below code example uses the Checker Framework's @NonNull
and @Nullable
annotations, but the Nullness Checker also supports @NotNull
so you can continue using JetBrains annotations in your code.
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.FieldInvariant;
class Parent {
final @Nullable String name;
Parent(@Nullable String name) {
this.name = name;
}
Driver createDriver() {
return new CommonDriver(name);
}
}
@FieldInvariant(qualifier = NonNull.class, field = "name")
class ChildC extends Parent {
ChildC(@NonNull String name) {
super(name);
}
@Override
Driver createDriver() {
return new ChildCDriver(name);
}
}
interface Driver {}
class CommonDriver implements Driver {
CommonDriver(@Nullable String name) {}
}
class ChildCDriver implements Driver {
ChildCDriver(@NonNull String name) {}
}