I have a method that can return a null value.
Use the return type of Optional to let callers know they need to handle absent values.
In this example the null check is needed because the city code may not exist in the repository.
However, it is not clear from the findCity method that a null could be returned.
When it is possible for a null to be returned from a method use an Optional wrapper class to let the caller know what to expect and that they need to handle the case where the value is absent.
The optional class contains the instance that can be null and offers several convenience methods to elegantly handle the null condition. Java 8 users should use the java.util.Optional version - since it is integrated into the various Java 8 APIs. For other users there is a version in the Google Guava framework.
Refactoring the null check example results in the following new implementation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void validateCity(String cityCode) { | |
Optional<City> city = findCity(cityCode); | |
if (city.isPresent()) { | |
return; | |
} | |
setError(CITY_INVALID, cityCode); | |
} | |
public Optional<City> findCity(String cityCode) { | |
City city = cityRepository.get(cityCode); | |
return Optional.ofNullable(city); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void optionalCreationExamples() { | |
// city can be null | |
Optional<City> optionalCity = Optional.ofNullable(city); | |
// cannot be null or NullPointerException is thrown | |
Optional<City> presentCity = Optional.of(city); | |
// creates a empty or not present instance of optional | |
Optional<City> absentCity = Optional.empty(); | |
} | |
public void optionalCheckIfValuePresent() { | |
if (optionalCity.isPresent()) { | |
// we have a value | |
} | |
// When present call Consumer function | |
optionalCity.ifPresent(City::setIsUsed); | |
} | |
public void optionalGetValue() { | |
// returns the city when present or NullPointerException if absent | |
City city1 = optionalCity.get(); | |
// returns the city or a default instance if absent | |
City city2 = optionalCity.orElse(DEFAULT_CITY); | |
// returns the city or hey, I'll just make a new one (uses supplier function) | |
City city3 = optionalCity.orElseGet(() -> new City(cityCode)); | |
// returns the city or throws the exception (uses supplier function) if absent | |
City city4 = optionalCity.orElseThrow(() -> new IllegalStateException("Invalid City Code")); | |
} |
No comments:
Post a Comment