Abstract


public Optional<User> findUserById(int id) {
    try {
        // Assume this fetches data or returns null if no data
        User user = database.queryForObject("SELECT * FROM users WHERE id = ?", id);
        return Optional.ofNullable(user);
    } catch (SQLException e) {
        // Handle database error, e.g., log it or rethrow as a custom exception
        throw new RuntimeException("Database error occurred", e);
    }
}
 
// Calling the method
try {
    Optional<User> userOpt = findUserById(1);
    userOpt.ifPresentOrElse(
        user -> System.out.println("User found: " + user.getName()),
        () -> System.out.println("No user found")
    );
} catch (RuntimeException e) {
    System.err.println("Error fetching user: " + e.getMessage());
}

Important

Optional focuses on data presence, while exceptions handle operational issues, such as database connectivity. By returning Optional.empty() for missing data, the caller knows it’s not an error, it’s simply an empty result. Without Optional, it’s unclear whether null means “no data” or “method failed.” With Optional, the intent becomes explicit.

Java Optional is a Maybe Monad.

Attention

We shouldn’t overuse Optional. It should be used as a return type to indicate whether the returned object contains a value or is empty. Avoid using it as a parameter!

References