2

I'm developing an android application using kotlin and the Android Studio auto completion menu is showing this (I'm elaborating a server response)

enter image description here

As you can see message and status are two strings, but one is the first is marked as String! and the other one as String, but I don't get the difference

I tried to check in the (java) source code and status is marked as @NonNull, while message does not have any annotation, but if the String can be null in this case in kotlin I should access to it using the !! operator and it should be marked with ?, not with !, because it would be of type String?.

What is going on here?

ci0ccarellia
  • 795
  • 9
  • 26

2 Answers2

2

The types marked with ! come from Java and they are called platform types. It means that the Kotlin compiler does not know if the value can be null or not, because there were no nullability annotations found for them.

From the official documentation:

Null-checks are relaxed for such types, so that safety guarantees for them are the same as in Java

You should be careful with these types because they can cause runtime exceptions:

When we call methods on variables of platform types, Kotlin does not issue nullability errors at compile time, but the call may fail at runtime, because of a null-pointer exception or an assertion that Kotlin generates to prevent nulls from propagating

Sergii Zhevzhyk
  • 4,074
  • 22
  • 28
1

In addition to Sergii's answer, Kotlin compiler supports a set of annotations allowing it to infer the correct type as you mentioned in your question. The full list is available here and, at the moment, includes among the others:

  • JetBrains' @Nullable and @NotNull
  • Annotations provided by Android under package android.support.annotation

If you annotate a Java method with one of the supported annotations, then when calling that method from Kotlin you'll get "for free" the correct type, i.e., either String or String? as per your example.

If otherwise you can't edit the source code, but you know that a given method never returns null, then you can "force" the type you want by explicitly typing your variable (as described here). Example:

val url: String = result.checkpoint_url

In this way your url variable won't be a String! anymore, but it will be forced to be a String. Similarly, you can do the same with val url: String? = xxx. Please note, though, that while the latter never fails (since it can contain both a nullable and a non-nullable string), the former can fail if result.checkpoint_url actually is null, and in such a case a runtime exception will be thrown.

user2340612
  • 10,053
  • 4
  • 41
  • 66