javachecker-framework

Iterating Over Nullable Error - Checker Framework


I am integrating checker framework to our project. One issue I get is the iterating.over.nullable. I am not sure why I get this error since I validate the list using CollectionUtils.isEmpty() before accessing the elements of the list.

The list item is Nullable but as I understand, since I do the check before accessing, it should not raise the error. Appreciate if someone could point out what I am doing wrong. Below is the code. I get the error iterating.over.nullable in line 4.

public List<MyCustomObject> map(Delivery delivery) {
    List<MyCustomObject> delList = new ArrayList<>();
    if (!CollectionUtils.isEmpty(delivery.getDeliveries())) {
        for (MyCustomObject deliveries : delivery.getDeliveries()) {
            //Processing code
        }
    }
    return delList;
}

Thanks in advance.

  1. Tried with the CollectionUtils.isEmpty since it checks the list is null or empty

Solution

  • The Nullness Checker has identified a genuine problem, and the best solution is not to suppress the warning. The problem might be in your code or in your annotations.

    Problems like this, and their solutions, are discussed in the Checker Framework manual, in section Side effects, determinism, purity, and type refinement.

    In the if test, delivery.getDeliveries() evaluated to a non-null and non-empty value. However, there is no guarantee that the second call in the for loop also evaluates to a non-null and non-empty value.

    Therefore, it is indeed possible that, in the for loop, delivery.getDeliveries() is null and a NullPointerException could occur at run time.

    One approach is to extract the expression into a local variable:

    Collection<MyCustomObject> allDeliveries = delivery.getDeliveries();
    if (!CollectionUtils.isEmpty(allDeliveries)) {
      for (MyCustomObject deliveries : allDeliveries) {
        // Processing code
      }
    

    Another approach is to declare the getDeliveries() method as @Deterministic.