Interoperability java-kotlin Nullable string crashing at runtime but why?

Viewed 19

I have an alternative to my problem, but I still have 2 questions:

  • Why it's crashing
  • Why Intellij/compiler is not complaining

I provided a small example of my issue. Here is an overview (you can find the code just after)

  • Car.java is the java class with a simple getter annoted as nulllable
  • MyView.kt is the crashing at runtime example with no warning in Intellij or in gradle. (Crashing when the value is null)
  • MyView2.kt is not crashing at runtime (even if mType is null)
  • Library.kt (kotlin stdlib) is simply the expected call for the example (even if it's weird to see string.toString())

Car.java

    @Nullable
    private String mType;

    @Nullable
    public String getCarType() {
        return mType;
    }

MyView.kt (crashing)

    val test: String = myCar.carType.toString()

MyView2.kt (not crashing)

    val carType: String? = myCar.carType
    val test2: String = carType.toString()

Library.kt (kotlin stdlib)

    /**
     * Returns a string representation of the object. Can be called with a null receiver, in which case
     * it returns the string "null".
     */
    public fun Any?.toString(): String

Thanks! I guess this is a corner case of the interop between kotlin and java? Or... someone is aware of a better explanation?

1 Answers

The clue to this difference is the optional marker ? in this line in MyView2.kt

val carType: String? = myCar.carType

- here you are declaring to the Kotlin compiler that you know that carType is nullable. (In turn the behaviour of .toString() will work even though it is called on a null object, as you showed from the docs.)

However things are different in MyView.kt because the code doesn't get as far as the .toString() call. Here you are directly using a platform type (i.e. Java) where null-safety rules cannot be deduced.

This documentation about Calling Java code from Kotlin explains:

Types of Java declarations are treated in Kotlin in a specific manner and called platform types. Null-checks are relaxed for such types, so that safety guarantees for them are the same as in Java

Related