Search code examples
javagetter-setternotnull

@NotNull implication on Getter and Setter of a Parameter


Believing and using Which @NotNull Java annotation should I use?, I have a class which has certain fields marked as @NotNull [package javax.validation.constraints] to pass on to the clients. The class also implement the default getter and setter for such fields. Sample class below -

public class MyClass 
{
    public MyClass() {
    }

    @NotNull
    private String name;

    private Boolean bool;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Boolean isBool() {
        return bool;
    }

    public void setBool(Boolean bool) {
        this.bool = bool;
    }
}

I am left a little puzzled up with the usage of the getter as follows in the business logic -

if(new MyClass().getName() !=null) {
    //do something
}

Is this null check not redundant, (if not) curious to know WHY?

Also if its redundant, would like to give a thought of setting a null value and getting the value of the param. Gave this a try as -

void test() {
    myClass.setName(null);
    if (myClass.getName() == null) {
        System.out.println("It should not be null"); // this got printed
    }
}

Solution

  • @NonNull is only a hint for your tooling, it does not affect how the java language itself handles nulls. It also requires every interaction to be properly annotated to ensure all mistakes are found.

    This happens in your case, while the name field is annotated the methods interacting with that field are not, so the tooling cannot make any assumptions about those methods and their nullability.

    However if you introduce more annotations like this:

    public void setName(@Nullable String name) {
        this.name = name; // should now have a warning
    }
    
    @NonNull
    public String getName() {
        return name;
    }
    

    Now the tooling should indicate new MyClass().getName() != null as always true. It also warns in setName that you're setting a nullable value to a non-null property and that is probably wrong.

    The way that is fixed:

    public void setName(@NonNull String name) {
        // setName(null) would cause a warning
        // Also add an exception if the annotation is ignored.
        this.name = Objects.requireNonNull(name);
    }
    
    /* or */
    
    public void setName(@Nullable String name) {
        if (name == null) return; // Guard against setting null
        this.name = name;
    }