In theory, the main reason I could use Supplier as a whole is, as @Eugene says in his answer , to delay execution. In practice, however, I never had a reason to use BooleanSupplier specifically. Moreover, it is very difficult for me to come up with a use case in real life ...
Despite this, I think it might seem typical to use a Supplier<String> . Hope this can shed light on the use of suppliers in general.
A typical example is logging. Suppose you need to register the result of a very expensive calculation that returns a value, but only when the log level is set to DEBUG . Let's say that this very expensive calculation is represented by the veryExpensive() method, which returns a value (the return type is not important for the example).
The traditional use pattern is to use an if , so we do a very expensive calculation when the DEBUG log level is turned on:
if (logger.isDebugEnabled()) { logger.debug("veryExpensive() returned: " + veryExpensive()); }
This works as expected, because if the log level is set to, for example, INFO , we will never call veryExpensive() . But now imagine that you have the same pattern repeating throughout your code. Pretty nice, hmm? A simple task, such as logging, has polluted all your code with an if ... application (And I do not invent it, I really saw this template many times).
Now think about what happens if logger.debug accepts a Supplier<String> instead of a simple String value. In this case, we no longer need the if , since the logic for extracting the String value into the log will now be in the implementation of the logger.debug method. Now use pattern:
logger.debug(() -> "veryExpensive() returned: " + veryExpensive());
Where () -> "veryExpensive() returned: " + veryExpensive() is a Supplier<String> .
This works very well because the execution of veryExpensive() delayed until the logger.debug method logger.debug needs to register the String returned by Supplier<String> , and this will only happen if the DEBUG log level is enabled.