I was using a third-party Java library. At some point they added @Nullable
and @NotNull
annotations. Unfortunately some methods (illustrated as Legacy::nullString
in the example below) were marked as @NotNull
, but in fact they could return nulls. I had safe-calls to protect from such cases, but they didn’t work, and I got NullPointerException. The problem was that I didn’t specify type of the B::x
field explicitly, and it’s type was automatically determined as not null.
As Kotlin compiler got sure that the B::x
field could not be null, it simply ignored all safe calls that followed (x?.length
), which resulted into crash. I think that it is wrong behavior, and that type of B::x
should be String?
, but not String
. This will introduce additional null check and can possibly affect performance, but as long as warnings are displayed, I think that it should be responsibility of the author of the code.
class Legacy {
val nullString: String = getNull()
val uninitialized: String = "unused"
fun getNull(): String {
return uninitialized
}
}
class B {
val x
get() = Legacy().nullString?.plus("0")
}
fun main(args: Array<String>) {
print(B().x?.length) // java.lang.NullPointerException
}