Let's say I have particular code in old/legacy Java library:
public class JavaClass {
private String notNullString;
private String nullableString;
private String unannotatedString;
public JavaClass(@NotNull String notNullString,
@Nullable String nullableString,
String unannotatedString) {
this.notNullString = notNullString;
this.nullableString = nullableString;
this.unannotatedString = unannotatedString;
}
@NotNull
public String getNotNullString() {
return notNullString;
}
@Nullable
public String getNullableString() {
return nullableString;
}
public String getUnannotatedString() {
return unannotatedString;
}
}
The first two parameters are properly annotated with @NotNull and @Nullable annotations (using jetbrains.annotations). The third one (unnanotatedString) is left without proper annotation.
When I use this class in my Kotlin code and set all the constructor arguments to non-null values, everything is fine:
val foo = JavaClass("first string", "second string", "third string")
println("Value1: ${foo.notNullString.length}")
println("Value2: ${foo.nullableString?.length}")
println("Value3: ${foo.unannotatedString.length}")
The first value is non-null so I can access it without a safe call. Second value and I need to use safe call (nullableString?.length), if not, I have a compile-time error, so far so good. On the third value (unannotatedString) I can use it without a safe call, it compiles fine.
But when I set the third parameter to "null" I don't get a compile-time error (no safe call required, only runtime NullPointerException:
val bar = JavaClass("first string", "second string", null)
println("Value4: ${bar.unannotatedString.length}") // throws NPE
Is that expected behaviour? Is Kotlin's compiler treating not annotated Java methods same as the ones annotated with @NotNull?