Mastering Null Handling in Java: Optional, Null Object Pattern & JSR 303/305
This article examines common pitfalls of null values in Java backend code, explains why returning null collections or objects can cause NullPointerExceptions, and presents robust solutions such as returning empty collections, using Optional, applying JSR‑303 validation, JSR‑305 annotations, and the Null Object pattern to improve API safety and readability.
Introduction
In many Java projects, excessive null‑value checks make the code hard to read and can lead to unexpected NullPointerExceptions. This article summarizes several techniques for handling nulls safely.
Scenario: UserSearchService
The service provides two methods:
public interface UserSearchService {
List<User> listUser();
User get(Integer id);
}Problems
When listUser() returns null, callers must perform null checks, risking NPEs.
When get(id) returns null, callers cannot know whether the user was not found or an error occurred.
Improved listUser
public List<User> listUser(){
List<User> userList = userListRepository.selectByExample(new UserExample());
if (CollectionUtils.isEmpty(userList)) {
return Lists.newArrayList(); // return empty list instead of null
}
return userList;
}Returning an empty collection eliminates the need for null checks.
Improved get
/**
* Retrieve user by id.
* @param id user id
* @return user entity
* @exception UserNotFoundException if the user does not exist
*/
User get(Integer id);Documenting possible exceptions makes the contract explicit.
Optional as Return Value
public interface UserSearchService {
Optional<User> getOptional(Integer id);
}Implementation:
public Optional<User> getOptional(Integer id) {
return Optional.ofNullable(userRepository.selectByPrimaryKey(id));
}Optional clearly expresses the existence or absence of a value.
Null Object Pattern
static class NullPerson extends Person {
@Override
String getAge() { return ""; }
@Override
String getName() { return ""; }
}When a Person is missing, return a NullPerson to avoid NPEs while keeping the API simple.
Parameter Validation (JSR‑303)
public interface UserSearchService {
/**
* Get user by id.
* @param id must not be null
* @return user entity
* @exception UserNotFoundException
*/
User get(@NotNull Integer id);
}Using Bean Validation enforces required parameters at runtime.
Documentation Annotations (JSR‑305)
public interface UserSearchService {
/**
* Get user by id.
* @param id user id
* @return user entity, may be absent
*/
@CheckForNull
User get(Integer id);
}Annotations like @Nullable, @Nonnull, and @CheckForNull provide compile‑time hints without changing runtime behavior.
DTO Conversion Example
PersonDTO personDTO = new PersonDTO();
Person person = getPerson();
if (person != null) {
personDTO.setDtoAge(person.getAge());
personDTO.setDtoName(person.getName());
} else {
personDTO.setDtoAge("");
personDTO.setDtoName("");
}Using Optional simplifies the conversion:
Optional.ofNullable(getPerson()).ifPresent(p -> {
personDTO.setDtoAge(p.getAge());
personDTO.setDtoName(p.getName());
});Best‑Practice Summary
Return empty collections instead of null.
Use Optional for values that may legitimately be absent.
Apply JSR‑303 for mandatory parameters and JSR‑305 for documentation.
Avoid using Optional as a method parameter.
Do not overload getters with Optional in Java beans; it pollutes the code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
