It’s said that using Optional will solve all the NullPointerExceptions. Is it really true? Or a we just using the Optional as a way to check the null values?
What is the best way to use Optional?
Null Checks
Null checks are like seat belts in a car: if you’re not using them, you’re inviting trouble. Every time you’re handed a variable, you need to ask: “Are you null?” And if you forget to ask, BOOM, NPE strikes again.
public float computePrice(Cart cart) {
float totalPrice = 0.0f;
if (cart != null) {
if (cart.getItems() != null) {
for (Item item : cart.getItems()) {
if (item.getUnitPrice() != null) {
if (item.getQuantity() != null) {
totalPrice += (item.getUnitPrice() * item.getQuantity());
}
}
}
}
}
return totalPrice;
}
Nevertheless, I’m tired to check them again and again.
So, is this behavior bad? Well, yes and no. On one hand, constantly checking for nulls everywhere can make your code look like it’s preparing for the apocalypse. On the other hand, ignoring null checks is like playing Russian Roulette with your app.
Should you stop using nulls altogether? Let’s be real here: null is a fact of life in Java. Pretending it doesn’t exist won’t make it go away. Instead, you need to understand why a variable might be null in the first place. But we’ll get to that in the conclusion (because every good article needs a cliffhanger).
Theoretical Use of Optional
With the Optional, it’s the way Java says: “Hey, maybe there’s something here, maybe there’s not. But I’ll make you check first.” By wrapping your objects in an Optional, you’re effectively saying, “No nulls allowed!”
At first glance, this seems like a godsend. No more nulls, no more NPEs. But wait, if you’re constantly checking whether an Optional is present, isn’t that just… null checks with extra steps? And if you start calling .get() on an empty Optional, congratulations, you’ve just reinvented the NullPointerException (now it’s called a NoSuchElementException).
public float computePrice(Optional<Cart> cart) {
float totalPrice = 0.0f;
if (cart.isPresent()) {
if (cart.get().getItems().isPresent()) {
for (Item item : cart.get().getItems()) {
if (item.getUnitPrice().isPresent()) {
if (item.getQuantity().isPresent()) {
totalPrice += (item.getUnitPrice().get() * item.getQuantity().get());
}
}
}
}
}
return totalPrice;
}
I don’t think I’ve a better code.
So, does Optional really solve the problem? Not by itself. Treating it like a fancy null wrapper misses the point. Let’s move on to how it’s meant to be used.
Real Use of Optional
Here’s where things get interesting. The true power of Optional lies in its ability to embrace functional programming. Instead of obsessing over whether the value is present, you chain methods to elegantly handle the empty case. For example:
public float computePrice(Optional<Cart> cart) {
return cart.flatMap(c -> c.getItems())
.map(items -> items.stream()
.mapToDouble(item -> item.getUnitPrice().orElse(0.0f) *
item.getQuantity().orElse(0))
.sum())
.orElse(0.0f);
}
Now it’s better.
Let’s break it down:
- Using
maporflatMap, I read the value inside anOptional; - If there is no value inside, I fall into the
orElse.
No if-else jungle, no manual checks, no unnecessary drama. Just smooth, functional goodness. Optional is not about avoiding checks; it’s about writing more expressive and maintainable code.
Conclusion
Let’s go back to the million-dollar question: Should you stop using nulls? Not necessarily. Null isn’t the enemy; the problem lies in variables that shouldn’t be null but can be. Instead of treating symptoms with endless null checks or blindly wrapping everything in Optional, focus on designing your code to avoid ambiguity in the first place.
I’ve written another article about how to handle the null correctly, how to effectively use it.
And remember, Optional isn’t a silver bullet. It’s a tool, it’s part of a functional programming approach. So, the next time you’re about to throw a null into your codebase, ask yourself: “Do I need this? Or am I just being lazy?”



Leave a comment