1

In the code below. I found in Intellij Idea compiler that val a and val b by default are "val a: StringBuilder" & "val b: StringBuilder!"

what is the difference between the two? What's the difference between StringBuilder and StringBuilder! ? Thank you :)

fun main(){
    val a = StringBuilder().apply { // by default is val a : StringBuilder
        append("Hello ")
        append("from me")
    }
    println(a)

    val b = StringBuilder().run { // by default is val b : StringBuilder!
        append("Hello ")
        append("from me")
    }
    println(b)
}
  • `apply` will return itself (that it was called on). `run` will return the result of last line, i.e. it will propagate the return statement of `append("from me")` to `b`. Since the `append()` is defined in Java, and has no Nullability information, it is considered as JVM platform type in Kotlin. – Animesh Sahu Oct 10 '20 at 08:29

1 Answers1

3

The ! indicates a platform type. It means that the compiler can't tell whether the type is nullable or not, because it comes from Java (or another JVM language), which doesn't make the distinction between nullable and non-nullable types, and doesn't have an annotation (@Nullable or @NonNull) to indicate that.

As a result, the compiler won't be able to make its usual null checks, so you should take care.

If you know (from the documentation, or looking at the Java code, or whatever) whether the value could be null or not, it's a good idea to specify the type explicitly (as either nullable with a trailing ?, or non-nullable without).

In this case, the difference is that apply() returns the value it was called on; that's all Kotlin, so the compiler knows its type. However, run() returns the last value in the lambda, which is the result of the last append() call. That method is defined in Java (since StringBuilder is part of the Java standard library), so the compiler can't tell whether it's nullable or not. But it's clear from the documentation that the method simply returns the StringBuilder it was called on, and so cannot be null. So for safety, you could specify an explicit StringBuilder type (i.e. non-nullable) for b.

gidds
  • 16,558
  • 2
  • 19
  • 26