28
votes

When calling a non-nullability-annotated Java function from Kotlin, we get flexible-typed return values, denoted by exclamation marks, e.g. String!.

Kotlin silently allows assigning these flexible values to a normal non-null type, e.g. String, which can cause NullPointerExceptions at runtime.

I would prefer to get compiler warnings or errors for such assignments. Alternatively, treat platform types as equivalent to nullable types (e.g. String?).

As an example, with this Java code:

import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

public class NullTest {

    private String maybe() {
        if (SystemClock.elapsedRealtimeNanos() % 2 == 0) {
            return null;
        }
        return "ok";
    }

    public String annotatedNothing()            { return maybe(); }
    @Nullable public String annotatedNullable() { return maybe(); }
    @NonNull  public String annotatedNonNull()  { return "ok"; }

}

...and the following Kotlin code, I'd like to get errors on two new lines (see comments):

fun testnulls() {
    val obj = NullTest()

    val nullExact: String  = obj.annotatedNullable() // already gives an error
    val nullMaybe: String? = obj.annotatedNullable()
    val nullInfer          = obj.annotatedNullable()

    val okayExact: String  = obj.annotatedNonNull()
    val okayMaybe: String? = obj.annotatedNonNull()
    val okayInfer          = obj.annotatedNonNull()

    val bareExact: String  = obj.annotatedNothing() // I want a compiler error here
    val bareMaybe: String? = obj.annotatedNothing()
    val bareInfer          = obj.annotatedNothing()

    print("length " + nullExact.length)
    print("length " + nullMaybe.length) // already gives an error
    print("length " + nullInfer.length) // already gives an error

    print("length " + okayExact.length)
    print("length " + okayMaybe.length) // already gives an error
    print("length " + okayInfer.length)

    print("length " + bareExact.length)
    print("length " + bareMaybe.length) // already gives an error
    print("length " + bareInfer.length) // I want a compiler error here
}

The point is that this will force me to add null checks or !!, making sure that I at least have to be explicit about it.

Is this possible?

In the comments of this 2014 JetBrains blog post, when they introduced platform/flexible types, it sounds like they were planning to add an option to warn about exactly these situations, but I haven't been able to find any further information on that.

3
If you want to have more information why JetBrains introduced the platform types, there is a good video of Andrey Breslav (see: youtube.com/watch?v=2IhT8HACc2E). He gives also a explanation why they didn't go the safest way.lampenlampen
Hi. Were you able to achieve this somehow?Arka Prava Basu
Unfortunately, no.Snild Dolkow
Every time I see a NullPointerException it is because of this and I shake my fist in anger at Jetbrains. I understand their motivation, but personally I would rather just use null-safe accessors every time I touch a java object. It's really not that inconvenient. Unfortunately I miss a lot of them because the compiler does nothing to help me.Drew Nutter

3 Answers

3
votes

Yes, it is possible to get compiler warnings and/or errors for any assignments from Java methods with a strong assumption that if method doesn't have @NotNull annotation it is @Nullable.

How? :) You will have to write your own Idea Custom Inspection plugin.

Here are some helpful links for anyone experienced enough to build that custom inspection plugin (probably I would be among its grateful users):

  1. Idea plugin development Quick Start Guide
  2. Sources of all existing Idea Kotlin Inspections (might be useful as examples of existing null safety checks)

If you are familiar and experienced Idea plugin developer, then it might not take a lot of time. Otherwise I don't think the result you are going to achieve will really worth the time you will have to spend.

I like your idea, but AFAIK at the early stages of kotlin development there was an attempt to implement as full null safety checks as possible and it turned so, that there were too many potentially unsafe assignments.

p.s. If you will finally build that inspection plugin please let me know. I personally tried to make it, but in my case I will have first to learn more about Idea plugins.

0
votes

The Kotlin documentation describes this exact case:

Any reference in Java may be null, which makes Kotlin's requirements of strict null-safety impractical for objects coming from Java. Types of Java declarations are treated specially in Kotlin and called platform types. Null-checks are relaxed for such types, so that safety guarantees for them are the same as in Java

Unfortunately, it means that there is no way to issue a warning during a compilation time. The silver lining is that Kotlin will at least prevent the null from propagation in runtime.

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

If I don't control the source code of a Java library that I use, I treat all of the results as potentially nullable, unless it is evident that they are not.

-2
votes

for non-null Strings -

check isEmpty(). You will not be able to pass non null strings in that method. So it is type safe.

for null Strings -

you can check null in if condition.