Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Condition is always false" warning from the compiler on condition which can actually be true

I have an interface with a method like this:

public interface MyInterface {
    void myMethod(@Nonnull String userEmail);
}

The interface has the following implementation:

public class MyInterfaceImpl implements MyInterface {
    @Override
    public void myMethod(@Nonnull String userEmail) {
        if ((userEmail== null) || !userEmail.endsWith("something")) {
            throw new SomeException("...");
        }
        ...
    }
}

The compiler is raising me a warning saying that Condition 'userEmail == null' is always 'false', but that doesn't look right.

As for my understanding, the annotation javax.annotation.Nonnull will warn the compiler in case someone calls my method with a null value, but does not prevent the code to compile if someone passes a null value to it. So yes, my code can be called with a null value at some point:

Compiler warning


Debugging with a null value

Note that I get the same warning if I compile on command line with the option -Xlint:all (so it does not look like just a bug in my IDE).

Does anyone have any idea how can I get rid of this warning and why is it occurring?

Disclaimer: the example I showed is just an example, the actual code does some stuff before to get to that condition, but nothing that can make userEmail == null always false (as it's proven by the debugger screenshot that I attached).

like image 691
Matteo NNZ Avatar asked Oct 22 '25 00:10

Matteo NNZ


2 Answers

As a lot of people mentioned in the comments already. It is behaving as it is intended. The explanation from https://checkerframework.org/manual/#nullness-checker clearly states what is going on here:

The checker issues a warning in these cases: When an expression of @NonNull type might become null, because it is a misuse of the type: the null value could flow to a dereference that the checker does not warn about.

The above warning only shows up when you pass -Alint=redundantNullComparison to the compiler and is by default turned off. As you are compiling with -Xlint:all even this warning is being enabled.

If you don't want to see this warning on itellij you can update your settings:

Settings (Ctrl+Alt+S / ) > Editor > Inspections > Java > Declaration redundancy > Null-check method is called with obviously non-null argument.

or

Settings (Ctrl+Alt+S / ) > Build, Execution, Deployment > Compiler > Add runtime assertions for not null annotated methods and parameters

or

Settings (Ctrl+Alt+S / ) > Editor > Inspections > Java > Probable bugs

Also if you are expecting a null value, it doesn't seem right to use that annotation in the first place.

like image 150
deepakchethan Avatar answered Oct 23 '25 15:10

deepakchethan


You have the annotation on the method parameter. @Nonnull String userEmail

So it expects that userEmail== null will always evaluate to false and hence no reason to be there in that if check.

Check the following answer regarding the @Nonnull which belongs to JSR 305

305 is about new annotations where you can already put them, which can help provide programmatic visibility into a design by contract system. So that if a certain method is supposed to not return null, or if a certain method is supposed to never receive a null parameter

So if you as a programmer have the confidence to annotate that parameter as nonNull, why shouldn't it report that the check userEmail == null has no meaning? With the annotation is like you inform the compiler that you have the confidence that it will never get called with null.

Annotation @Nonnull is like describing a contract. You don't make contracts which you know could be broken. If you are not sure then remove the annotation. If you are sure then remove the check userEmail == null

like image 33
Panagiotis Bougioukos Avatar answered Oct 23 '25 14:10

Panagiotis Bougioukos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!