Check for null object and null value contained in object in Java 8 way

For the first case I would use: Objects.requireNonNull().

I don't think Optional is a way to go here as null is an illegal value.


You've got a pattern condition -> throw an exception which can be moved to a method:

private void checkOrElseThrow(boolean condition, Supplier<? extends RuntimeException> exceptionSupplier) {
    if (condition) {
        throw exceptionSupplier.get();
    }
}

public void setMemory(List<Integer> memory) {

    checkOrElseThrow(memory == null, () -> new IllegalArgumentException("message #1"));
    checkOrElseThrow(memory.contains(null), () -> new IllegalArgumentException("message #2"));

    this.memory = memory;
}

If the type of the exception is not going to be changed, it's reasonable to pass only the message of the exception (thank @tobias_k for pointing it out):

private void checkOrElseThrow(boolean condition, String exceptionMessage) {
    if (condition) {
        throw new IllegalArgumentException(exceptionMessage);
    }
}

public void setMemory(List<Integer> memory) {

    checkOrElseThrow(memory == null, "message #1");
    checkOrElseThrow(memory.contains(null), "message #2");

    this.memory = memory;
}

I usually avoid Optional for such cases as it tends to obscure what's going on.

But first I'd like to mention that the original code lets the caller retain a reference to what is now an internal field memory of the containing class. Maybe you trust your callers not to be malicious, but the caller might accidentally reuse the list passed as an argument. If it does, despite the meticulous argument checking, the memory list might end up containing nulls after all. Or, it could change unexpectedly, leading to other malfunctions.

The solution is to make a defensive copy of the argument list. The straightforward way to do this is as follows:

public void setMemory(ArrayList<Integer> memory) {
    if (memory == null)
        throw new IllegalArgumentException("memory is null");

    List<Integer> temp = new ArrayList<>(memory);

    if (temp.contains(null))
        throw new IllegalArgumentException("memory contains null");

    this.memory = temp;
}

Note that the copy is made and stored in a local variable temp prior to being checked. Obviously, you don't want to store into the field before the list is checked for containing nulls. But the check for containing nulls should be done on the copy, not on the argument list, otherwise, the caller could modify the list after the check but before the copy. (Yes, this is being paranoid.)

If you don't care about the exact exception message, this could be shortened as follows:

public void setMemory(ArrayList<Integer> memory) {
    List<Integer> temp;
    if (memory == null || ((temp = new ArrayList<>(memory)).contains(null)))
        throw new IllegalArgumentException("memory is or contains null");
    this.memory = temp;
}

Now this could be rewritten to use Optional:

public void setMemory(ArrayList<Integer> memory) {
    this.memory = Optional.ofNullable(memory)
                          .map(ArrayList::new)
                          .filter(list -> ! list.contains(null))
                          .orElseThrow(() -> new IllegalArgumentException("memory is or contains null"));
}

Compared to the usual abuses :-) of Optional I see frequently, this one isn't too bad. The chaining here serves to avoid creation of a local variable, which is a bit of a win. The logic is fairly straightforward, especially if one has Optional on the forebrain. However, I'd be somewhat concerned about revisiting this code in, say, a month. You'd probably have to squint at it a while before convincing yourself it does what you intended it to do.

Finally, a couple general style comments.

  1. The usual preference (at least in the JDK) is to use NullPointerException for these cases. I've stuck with IllegalArgumentException for these examples because that's what the OP is using.

  2. I'd recommend using List<Integer> instead of ArrayList<Integer> for the argument type and possibly the field type. This will enable the use of unmodifiable lists in situations where it's appropriate (e.g., using JDK 9's List.of).


If you want to stick to IllegalArgumentException and you have guava on the class path, you could use this:

Preconditions.checkArgument(memory != null, 
            "ERROR: memory object can't be null.");
Preconditions.checkArgument(!memory.contains(null), 
            "ERROR: memory object can't contain null value.");

You can't really use Optional here since you want different error messages for different conditions.

If you are OK having a single error message on the other hand, you could do:

this.memory = Optional.ofNullable(memory)
            .filter(x -> !x.contains(null))
            .orElseThrow(() -> new IllegalArgumentException(
                         "memory object is null or contains null values"));