Hello. I’m developing android app and I’ve met weird NPE since I migrate from 1.4.30 → 1.5.21.
It seems like a?.b is treated as non-null in 1.5.21.
(java-decompiled code is same for 1.4.30, 1.5.21)
What’s happening here?
class A(
val b: B
)
class B(
val c: String
)
fun createByReflection(): A? = A(B("aaa")).apply {
val field = javaClass.declaredFields.find { it.name == "b" }!!
field.isAccessible = true
field.set(this, null)
}
fun main() {
val a = createByReflection()
println(a?.b) // this outputs null of course.
println(a?.b?.c) // In 1.5.21, this throws java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String B.getC()' on a null object reference
}
Seems reasonable, b is non-null in A. Yet you’re hacking around with reflection to change that.
The compiler is very reasonable here in assuming b is not null.
If your code rely on an undefined behaviour (which your code very much is) , you are on your own. the Kotlin team probably don’t have test for that case and won’t add one, thus the lack of changelog for that.
If it is ‘undefined behavior’ then I agree that it doesn’t have to be in release note.
but I still wish there was a note or something.
(I used reflection directly in my example, but it was Gson in the production code.)
Ah, I see, that is unfortunate. If it is possible I would advise you to migrate to kotlinx.serialization, it’s reflection-free, written in kotlin, maintained by JetBrains and works a treat
Ohh, I’m actually surprised this went to YouTrack. Why is it considered a bug? I guess the generated bytecode should not check not-null variables for nulls. Or maybe we assume that ?. operator should enforce such check, even if used on a not-null?