Search code examples
javaintellij-ideaannotationsintellij-14

When to use @Contract("null -> fail") and when to use @NotNull


With the IntelliJ Annotations, it's possible to declare a failure of a function in case of a method parameter being null in two different ways (and combining them, that makes three in total):

I can use a @NotNull annotation on the method parameter to declare that the parameter should never be null.

@NotNull
public static String doSomething(@NotNull CharSequence parameter) throws NullPointerException {
    return String.format("This is the value: %s, of type %s",
            Objects.requireNonNull(parameter),
            parameter.getClass().getName());
}

Alternatively, I can use a @Contract("null -> fail") annotation, which declares that if the first parameter is null, the method will throw an exception.

@NotNull
@Contract("null -> fail")
public static String doSomething(CharSequence parameter) throws NullPointerException {
    return String.format("This is the value: %s, of type %s",
            Objects.requireNonNull(parameter),
            parameter.getClass().getName());
}

Lastly, I can even use both and nothing in my IntelliJ IDEA 14.1.4 is complaining:

@NotNull
@Contract("null -> fail")
public static String doSomething(@NotNull CharSequence parameter) throws NullPointerException {
    return String.format("This is the value: %s, of type %s",
            Objects.requireNonNull(parameter),
            parameter.getClass().getName());
}

Which of these three cases is the best to use?


Solution

  • In your case, I'd use @NotNull, because:

    • it's a more specific annotation and IDEA is able to produce more specific warnings based on it
    • IDEA can generate runtime assertions ensuring it's really not null

    @Contract annotation is a more powerful but less specific tool. It allows you to express much more complex contracts with the downsides that the resulting editor warnings might be more obscure, and there will be no runtime checks added automatically.