NullPointer exceptions assigning to kotlin.String result of Java methods


#1

Hi,

I picked up an interest in Kotlin after seeing the v1 release and was wondering how it would work with for instance JPA libraries such as EclipseLink or Hibernate, that populate fields from the database, and which might make something NULL which was supposed to be non-nullable…

So I decided to do another experiment and see if I could subvert the non-null promise of the compiler using other interactions with Java classes and yes, it seems that I can do that, although with slightly different behaviour in the REPL vs a compiled function.

In the REPL I can do something like:

var s: String = "non-nullable string"
s = System.getProperty("bad.property")
println("String s is now: ${s}")
println("Length of String s: ${s.length}")

And this will give an NPE on s.length

So the REPL breaks the promise of non-nullability.

In a .kt file I can also compile code which can give a NULL error, although at point of assignment this time:

fun main(args: Array<String>) {
    var s: String = "non-nullable string"
    println("String s: ${s}")
    var s2: String? = "something not null"
//    s = s2 // Gives compiler error

    println("Value of property 'user.name': ${System.getProperty("user.name")}")
    s = System.getProperty("user.name")
    println("String s is now: ${s}")
    println("Length of String s: ${s.length}")

    println("Value of property 'bad.property': ${System.getProperty("bad.property")}")
    s = System.getProperty("bad.property")
    println("String s is now: ${s}")
    println("Length of String s: ${s.length}")

}

There is no compiler error, but on attempting to assign NULL to s the runtime does throw an error.

Wouldn’t it be better if the compiler hadn’t allowed the assignment of a potentially NULL method-result to a non-nullable variable?

This way the language seems to break it’s promises of compile-time NULL safety and still give runtime errors related to NULL.

I realize this is all a bit late, so my apologies for that… :frowning:


#2

Compile-time null safety is only guaranteed when calling from Kotlin code into Kotlin code, or when calling from Kotlin code into Java code annotated with nullity annotations.

Earlier versions of Kotlin used to treat all Java method return values as nullable, but that proved too cumbersome in practice, and didn’t really help to solve the problem. I’m sure you can find more about this topic on the web. There was also an attempt to externally annotate the Java standard library, but unfortunately that was eventually deemed impractical as well.


#3

To provide a bit more detail, System.getProperty returns String! (which happens to be assignable to String), not String or String?. See the official docs for details.


#4

Thanks, that is an interesting and useful explanation in the documentation.