Kotlin call Java platform types result in llegalSt

2019-07-15 14:21发布

问题:

I'm using kotlin in one of my Android classes and it seems like an IllegalStateException sometimes pops up on this line, when trying to get an extra from a Bundle.

keyOrTag = bundle.getString("tag")

And the val is declared like this

val keyOrTag: String

Unfortunately I don't have the full stack trace as I've noticed this from the GP Console.

回答1:

Okay I believe I know why that happens. Posting it as an answer so that others with a related issue could see.

The String "tag" added to the bundle can actually be null in the Java class that sends it over to the Kotlin one. And since I didn't declare the val as nullable I believe that's why it's throwing an IllegalStateException (yup, no NPE in kotlin).

The fix:

val keyOrTag: String?


回答2:

When this error occurs?

The IllegalStateException was thrown by Kotlin kotlin.jvm.internal.Intrinsics possibly when you calling Java platform types.

Why did you can't see the stackTrace of an Exception throws by kotlin.jvm.internal.Intrinsics from Kotlin?

This is because the stackTrace is removed by Kotlin in Intrinsics#sanitizeStackTrace method internally:

private static <T extends Throwable> T sanitizeStackTrace(T throwable) {
    return sanitizeStackTrace(throwable, Intrinsics.class.getName());
}

Example

Here is a Java platform type StringUtils source code, and the toNull method will return null if the parameter value is null or "".

public class StringUtils {
    public static String toNull(String value) {
        return value == null || value.isEmpty() ? null : value;
    }
}

Then you try to assign the result of the method call to a non-nullable variable possibly throws an IllegalStateException, for example:

val value: String = StringUtils.toNull("")
//         ^
//throws IllegalStateException: StringUtils.toNull("") must not be null
//try to assign a `null` from `toNull("")` to the non-nullable variable `value`

How to avoiding such Exception throws by kotlin.jvm.internal.Intrinsics?

IF you are not sure that the return value whether is null or not from Java platform types, you should assign the value to a nullable variable/make the return type nullable, for example:

val value: String? = StringUtils.toNull("")
//         ^--- it works fine