I'm trying to write an immutable data class that uses @Nonnull to flag required parameters. Unfortunately whichever way I write it FindBugs flags a warning:
/**
* An error occuring during migration
*/
@Immutable
@ParametersAreNonnullByDefault
public static final class MigrationError extends MigrationResult
{
private final String message;
private MigrationError(String message)
{
this.message = message;
}
@Override
public boolean isSuccess()
{
return false;
}
@Nonnull
public final String getMessage()
{
return message;
}
@Override
public MigrationError asError()
{
return this;
}
}
As written, this results in a Correctness warning - Null pointer dereference, Method may return null, but is declared @Nonnull. I've tried adding a null check in the constructor:
private MigrationError(String message)
{
if (message == null)
{
throw new IllegalArgumentException("Error message cannot be null");
}
this.message = message;
}
The warning remains however, and I now have an additional warning from Intellij that 'message == null' is always false. If I add a null check in the getter:
@Nonnull
public final String getMessage()
{
if (message == null)
{
return "";
}
return message;
}
I get the same warning from IntelliJ and FindBugs gives me a new warning: Dodgy code: Redundant comparison to null: Redundant nullcheck of value known to be non-null. I get the same FindBugs warning if I remove the explicit null check and add @Nonnull
to the message
field.
I can suppress the warnings, but I'd like to know what FindBugs expects. Is there is some pattern for declaring an immutable field NonNull? Does it matter that it is a static nested class within its parent class?