My code reads some configuration values from DB. In case they are undefined (returned null by getValueFromDB method) I want to default them to values defined in config file.
Is it ok to use Optional.ofNullable().OrElse()
for all occurrences of getValueFromDB()
to do null check and assign default value in case of null.
Or will this be a misuse/abuse of Optional
?
In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional class forces you to think about the case when the value is not present.
What is the ofNullable() method of the Optional class? The ofNullable() method is used to get an instance of the Optional class with a specified value. If the value is null , then an empty Optional object is returned.
Optional was introduced to Java as a way to fix the issues with null references. Before Optional , every object was allowed to either contain a value or not (i.e. being null ). The introduction of Optional essentially enforces null -checking by the type-system making it unnecessary to perform such checks manually.
Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as 'available' or 'not available' instead of checking null values. It is introduced in Java 8 and is similar to what Optional is in Guava.
Well, we use this idiom in our code base like crazy - I see no problem what-so-ever with it. This is what Optional
is all about to me - forcing you to take an action if some value is present or not; what I absolutely love is that it is build in the language itself as of java-8 and I don't have to introduce additional methods for that (or libraries like guava
).
You might be thinking for this simple case here, but Optional
has other chained method as-well obviously, so I can do:
Optional.ofNullalbe(dbPass)
.map(// do mapping)
.filter(// do filtering)
.ifPresent(x -> // log it )
You can't easily achieve that with other methods.
It seems like a small abuse, but I don't feel strongly about it. Maybe if enough programmers start doing this, it will become an accepted idiom.
But you can do the same thing without using Optional
:
public static <T> T useValueOrDefault(T value, T defaultValue) {
return (value == null) ? defaultValue : value;
}
and use this method everywhere instead of Optional.ofNullable(value).orElse(default)
. (Note: not tested)
I do find that built-in constructs that accomplish this, like ||
in Javascript or ?:
in Kotlin, are useful. Too bad Java doesn't have an equivalent (EDIT: according to @Holger's comment, Java 9 has introduced one).
It feels excessively ornate to convert something to an Optional
only to immediately convert it back to the wrapped type using orElse
in the same method.
To me Optional
is more about exposing the possibility that a returned value might be empty, in a method's type signature. The Optional
type communicates to the consumer that it might be empty. If you created it with ofNullable
on the previous line of code, you are both the creator and the consumer, and already know that it might be null
-- so deal with it in-place without creating a new short-lived object.
However, Optional
fosters tidy code, and my first instinct is to ask whether your database API has the ability to return Optional.empty()
instead of null
, itself. This depends on the library you're using, and is possibly more likely in 2020 than it was when you asked the question in 2017.
In that case it would make perfect sense to use returnedOptional.orElse(default)
if that's the application logic.
If your database API can't give you an Optional
, I wouldn't, in the application logic, go via Optional
to do the defaulting. It's simpler and clearer to use:
return value == null ? default : value;
However I would consider adding a thin abstraction layer between your Optional-incapable database API and your application logic, that just does Optional.ofNullable()
where appropriate. Their DB library doesn't have the API you want, so wrap it to create the API you want. Your DB library has the courtesy to the caller, that when a value might be absent, the type signature says so.
So instead of:
MyType maybeS = theirDbLibrary.query(...);
MyType s = (maybeS == null) ? default : maybeS;
You'd have:
Optional<MyType> maybeS = myWrappedDbLibrary.query(...);
MyType s = maybeS.orElse(default);
The intent here is to remove all knowledge of null
from your application logic. If the core of your application has no reference to null
at all (including ofNullable
), that's really great. It removes lots and lots of opportunities for bugs. But for that to be possible you need to eliminate the possibility that a null
gets passed into your code -- and that's where your clean-up layer between the DB and your application code does its work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With