0

Random example: In the source code of one of my programs I have this method:

    public @NotNull Currency[] getCurrencies() {
        return this.currencies.values().toArray(new Currency[0]);
    }

Which, after being compiled, gets turned into the following by my IDE (Intellij):

    @NotNull
    public Currency[] getCurrencies() {
        Currency[] var10000 = (Currency[])this.currencies.values().toArray(new Currency[0]);
        if (var10000 == null) {
            $$$reportNull$$$0(4);
        }

        return var10000;
    }

this.currencies refers to private final ConcurrentHashMap<String, Currency> currencies = new ConcurrentHashMap(); - which means that only via means of reflection or cosmic rays causing bit flips, the method getCurrencies() could ever return null.

  • Should I - in such cases where there is no chance for a null being returned - forgo the usage of the @NotNull annotation?
  • Does the annotation even have significant impact on performance, or do the benefits of having the annotation outweigh the performance impact?

Thank you

/edit: I am using the annotation package org.jetbrains.annotations

jaylawl
  • 105
  • 6

2 Answers2

1

@NotNull is not an annotation for your compiler. The compiler might use this annotation and do some additional checks. But @NotNull is an annotation for the humans reading your code that the compiler checks. Of Java's many problems, the biggest by far is the prevalence of unchecked null values floating around everywhere. In an otherwise statically-typed language, any variable anywhere in your program may simply not exist and violate every guarantee the type checker could otherwise provide.

Kotlin has proper nullable types. Recent versions of Scala have (opt-in) nullable types. Even new versions of C# have nullable types. In Java, @NotNull should be considered part of your function's contract, almost part of its type. You're not saying "hey, compiler, check if this is null". You're saying "I guarantee this function will never return null" and the compiler is checking it, in the same way that declaring a return type of String is making a guarantee that you're returning a String. Removing the @NotNull annotation because you're sure it's right is tantamount to changing all of your return types to Object because you know in your head what types the functions return. If you think

String getName(String prefix) { ... }

looks better than

Object getName(Object prefix) { ... }

then you should think

@NotNull String getName(@NotNull String prefix) { ... }

looks even better. It's a stronger guarantee.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
0

Having a null check on your getter is a bit strange. At the time you call the getter your object is already in a state it shouldn't be in. You probably want to have the @NotNull on the parameter for your setter or constructor instead.

What you can do is write a JavaDoc for your getCurrencies.

/**
/* @return An array of currencies. Never null.
*/
public Currency[] getCurrencies() {}

But it's very uncommon to document that a method doesn't return null. Not returning null should be the gold standard and if a method can return null it should be documented, not the other way around. Also I wouldn't expect a getter that returns a set of data (arrays, lists etc.) to return null. Instead return an empty object.

magicmn
  • 1,787
  • 7
  • 15