Java
Null Handling Strategies
Null is the "billion dollar mistake" according to its inventor, Tony Hoare. This article covers strategies to eliminate null-related bugs: Null Object pattern, Optional, defensive coding, and static analysis tools.
📋 At a Glance
| Aspect | Details |
|---|---|
| Patterns Covered | Null Object, Optional, Defensive Coding |
| Primary Benefit | Eliminate NullPointerException |
| Java Version | 8+ (Optional), all (Null Object) |
| Tools | NullAway, Checker Framework, SpotBugs |
🎯 What You'll Learn
- Null Object Pattern for default behavior
- Optional proper usage and anti-patterns
- Defensive coding with fail-fast validation
- Static analysis for null safety
- When null is appropriate (yes, sometimes)
🔬 Deep Dive
Pattern 1: Null Object Pattern
JAVA(39 lines)CodeLoading syntax highlighter...
Pattern 2: Optional Proper Usage
JAVA(59 lines)CodeLoading syntax highlighter...
Pattern 3: Defensive Coding
JAVA(31 lines)CodeLoading syntax highlighter...
Pattern 4: Annotations for Static Analysis
JAVA(20 lines)CodeLoading syntax highlighter...
Pattern 5: Java 21+ Null in Pattern Matching
JAVA(25 lines)CodeLoading syntax highlighter...
⚠️ When Null is Appropriate
- Uninitialized lazy fields (with proper null checks)
- Absent optional data in domain (though Optional often better)
- Performance-critical code (Optional has overhead)
- Framework contracts (JPA entities, etc.)
🐛 Debug This: The Phantom Null
A developer reports: "We added Optional everywhere but still getting NullPointerException. I thought Optional was supposed to fix this!"
JAVA(19 lines)CodeLoading syntax highlighter...
Why does Optional fail to prevent NPE here? Find all the mistakes!
✅ Solution:
Three distinct Optional anti-patterns:
.get()without.isPresent()- defeats the purpose of Optional.orElse(null)- reintroduces null into the codebase.map()to Optional - null values inside Optional cause issues
Correct approach:
JAVA(20 lines)CodeLoading syntax highlighter...
The lesson: Optional only helps if used correctly. Never call
.get() without checking, never use .orElse(null), and handle nested nulls explicitly.💻 Exercises
Exercise 1: Eliminate Null Returns
⭐ Difficulty: Easy | ⏱️ Time: 15 minutes
Task: Refactor to eliminate null returns.
JAVA(18 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(10 lines)CodeLoading syntax highlighter...
Exercise 2: Implement Null Object Pattern
⭐⭐ Difficulty: Medium | ⏱️ Time: 20 minutes
Task: Replace null checks with Null Object.
JAVA(25 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(20 lines)CodeLoading syntax highlighter...
Exercise 3: Defensive Coding
⭐⭐ Difficulty: Medium | ⏱️ Time: 15 minutes
Task: Add fail-fast null validation.
JAVA(12 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(17 lines)CodeLoading syntax highlighter...
Exercise 4: Optional Chain Refactoring
⭐⭐⭐ Difficulty: Medium-Hard | ⏱️ Time: 20 minutes
Task: Refactor these null checks to Optional chains.
JAVA(12 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(7 lines)CodeLoading syntax highlighter...
Exercise 5: Static Analysis Setup
⭐⭐⭐⭐ Difficulty: Hard | ⏱️ Time: 25 minutes
Task: Add null-safety annotations and configure static analysis.
JAVA(6 lines)CodeLoading syntax highlighter...
✅ Solution:
JAVA(30 lines)CodeLoading syntax highlighter...
🎤 Senior-Level Interview Questions
Q1: When would you use Null Object vs Optional?
A:
- Null Object: When "nothing" has default behavior (NullDiscount applies no discount)
- Optional: When "nothing" means absence (no user found)
- Null Object is about polymorphic behavior, Optional is about presence/absence
Q2: What are Optional anti-patterns?
A:
- Calling
.get()without.isPresent()check - Using
.orElse(null)- reintroduces null - Using Optional as method parameters
- Using Optional for class fields (serialization issues)
- Creating Optional just to call
.isPresent()
Q3: How do you handle null in legacy code integration?
A:
- Wrap at boundary:
Optional.ofNullable(legacyMethod()) - Create adapter classes with null-safe API
- Add
@Nullableannotations for documentation - Use defensive
Objects.requireNonNull()at entry points
📝 Summary
| Pattern | Use When |
|---|---|
| Null Object | Need default behavior |
| Optional | Return values that might be absent |
| requireNonNull | Validate parameters |
| @Nullable/@NonNull | Static analysis |
📅 Review Schedule for This Article
| Day | Task | Time |
|---|---|---|
| Day 1 | Review Null Object vs Optional decision table | 5 min |
| Day 3 | Redo Exercise 1 (Eliminate Null Returns) | 15 min |
| Day 7 | Answer interview questions without looking | 10 min |
| Day 14 | Redo Debug This (Optional anti-patterns) | 10 min |
| Day 30 | Audit one class in your project for null-safety | 15 min |
Next: [Part 9: Builder & Factory Patterns]