28

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.

Snild Dolkow
  • 6,669
  • 3
  • 20
  • 32
  • 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 Aug 31 '17 at 15:42
  • Hi. Were you able to achieve this somehow? – Arka Prava Basu Sep 30 '19 at 09:27
  • Unfortunately, no. – Snild Dolkow Oct 01 '19 at 04:15
  • 3
    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 Jun 11 '20 at 03:42
  • Here's a forum post that seems relevant https://discuss.kotlinlang.org/t/compiler-option-s-proposal-provide-nullability-assumptions-when-interacting-with-non-annotated-java-code/11554 – Mike Oct 27 '21 at 18:34

4 Answers4

4

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.

Клаус Шварц
  • 3,158
  • 28
  • 44
  • contributing the idea of this warns check might be great by forking the actual Jetbrains/Kotlin repo – mochadwi May 08 '20 at 00:28
0

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.

oiavorskyi
  • 2,893
  • 1
  • 20
  • 23
  • 4
    Yes, I know that this is the documented behavior, but I was hoping for an option to change it, or maybe a code inspection for it in IntelliJ/Android Studio or something. The point of null-safe typing (at least, the biggest benefit that I can see) is to _not_ have to think about whether something could be null -- the compiler will shout at me if I get it wrong. I guess I just don't like the concept of platform types. Essentially, I want the compiler to help me enforce your recommendation: "treat all of the [Java] results as potentially nullable", unless I say (`!!`) that they're not. – Snild Dolkow Aug 15 '17 at 11:54
  • I agree. It would be nice to have at least some sort of flag to change the default behavior. The current behavior is probably a tradeoff Jetbrains team had to take in order to simplify interoperability and increase acceptance of the new language by Java folks. – oiavorskyi Aug 15 '17 at 12:01
  • I have tried to play with inspections in Intellij Idea to see if it is possible to change the default behavior. It doesn't look like changing `Function or property has platform type` from a weak warning to an error gives any results. – oiavorskyi Aug 15 '17 at 12:04
  • Hm. Yeah, it seems like that inspection warns if the return type of a function is a platform type, i.e. `fun bad() = NullTest().annotatedNothing()`. Not good enough, unfortunately. :/ – Snild Dolkow Aug 15 '17 at 12:12
0

I did some research and found some interesting links.

First as others have mentioned it seems like the Kotlin developers wants to avoid false positives and here is a discussion on adding a compile time option to mark platform type usage: https://youtrack.jetbrains.com/issue/KTIJ-6891 Which the kotlin team seems reluctant to add.

However I found that the developers of detekt (a static code analysis tool for kotlin) have an open issue on adding detection of platform type usage: https://github.com/detekt/detekt/issues/3603

And it seems like they are relatively close to adding this. https://github.com/detekt/detekt/pull/4470/files

So hopefully that will help developers catch those NPE's before the users does.

dc-fwh
  • 1
  • 1
-3

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.

H.Jain
  • 21
  • 2
  • Please read the full text of the question before answering. This answer doesn't answer the question that was asked. – Jade May 20 '18 at 18:36