When pass an object to a function, then there is a scenario which always arises. That, the passed object could be null.
And, we have to write logic to react to that null-condition. And, generally that logic is hard-coded in the function.

And, there are times as a user I feel that, instead of throwing an exception this function should have done something else.

You can watch my video to get a lot more from this article.

 

For example, I am taking two functions which calculates some values and handles null-case.

Case 1 : Throws an exception

public Double calculatBaseSalary( final Person person ) {
    if(person == null) throw new IllegalArgumentException("Person can not be null");

    return person.salary * .8d;
}

Case 2 : Returns a default value

public Double calculateBaseSalaryDefaultValue(final Person person) {
    if(person == null) return PERSON_DEFAULT_SALARY;
    return person.salary * .8d; 
}

If I call above function, in my code, either it is going to throw an exception or return a default value. And, I do not want any of this scenario.
As, a user I should have freedom to decide what to do in these cases.

So, we can write code, that takes a function as input.

public Double calculateBaseSalaryNullThenElse(final Person person, final DoubleSupplier doubleSupplier) {
    if(person == null) return doubleSupplier.getAsDouble();
    
    return person.salary * .8d;
}

In the above code, I am passing a doubleSupplier, which can be used by me to get a response that I want. And, I can change the returned value as I see fit.

Case 1 : Throws an exception

nullTest.calculateBaseSalaryNullThenElse(person, 
                                            () -> { 
                                                    throw new IllegalArgumentException("Person object can not be null.");
                                                  }
                                        );

So, If person  object is null then throw an IllegalArgumentException. That’s it, If I want an exception then exception can be thrown.

Case 2 : Returns a default value

nullTest.calculateBaseSalaryNullThenElse(person, () -> 1d);

In the above code, I return 1d as the default value, in case person  object is null. If some requirement change comes, where we need to have different value.
Then we can just modify the supplier to supply different default value.

 

The same way, we can move the logic to calculate the salary to a function object. Which makes this function more flexible.
If you want to know, how to do it. You can watch my youtube video for that.