I have gone through several null check related questions in Java and the best practices around it.
After long search , I can see Objects.nonNull () serves the purpose though it looks Orange instead of Apple.
Now i have a following check using Objects.nonNull() and short-circuiting logical AND.
if (Objects.nonNull (obj1) &&
Objects.nonNull (obj1.getObj2()) &&
Objects.nonNull (obj1.getObj2().getObj3 ())
{
obj1.getObj2().getObj3().doSomething();
}
I find it is more redundant and less readable when i clearly know my intention.
Is there any other approach to handle it in functional way to assert the non null state of the deeper object without facing Null pointer exception.
Using !=null is the normal way to do null-checks, but here's an alternative way that allows you to chain them using Optional.
Optional.ofNullable(obj1).map(class1::getObj2)
.map(class2::getObj3)
.ifPresent(class3::doSomething);
and you can use a lambda expression in place of any of the method references if the code you want to execute is not a simple function call.
Optional.ofNullable(obj1).map(x -> x.getObj2())
.map(x -> x.getObj3())
.ifPresent(x -> {
System.out.println("Now I can use my obj3 "+x);
});
Related
We have all seen that kind of code
if (myObject!= null
&& myObject.mySubObject() != null
&& myObject.mySubObject().getSpecificValue() != null
&& !myObject.mySubObject().getSpecificValue().isEmpty()
) {
......
}
How could I write this the clean way ?
You can do chaining with Optional:
Optional.ofNullable(myObject)
.map(o -> o.mySubObject())
.map(so -> so.getSpecificValue())
.map(sv -> sv.isEmpty())
.orElse(false)
Or with method references even shorter (does the same):
Optional.ofNullable(myObject)
.map(Foo::mySubObject)
.map(Bar::getSpecificValue)
.map(Baz::isEmpty)
.orElse(false)
where Foo, Bar and Baz are the names of the respective classes.
If you are using someone else's code then you're really stuck handling for a possible null. On the other hand, if you have control over the code base then never return a null object, and make that a rule across your entire application.
This may sound bad at first but I have developed several enterprise-level applications and this is a very effective way to make the code consistent and much more readable.
So, now, this
if (myString != null && !myString.isEmpty()) {
becomes simply
if (!myString.isEmpty()) {
In lue of that option use the new Optional feature in J8 as it is intended for that purpose.
A super simple question:
Here's my plain Java code using traditional ternary operator ?
public DateTime getCreatedAt() {
return !recordA.isPresent() ? recordB.get().getCreatedAt() : recordA.get().getCreatedAt();
}
My best bet is following:
public DateTime getCreatedAt() {
return recordA.map(
record -> record.getCreatedAt())
.orElse(recordB.get().getCreatedAt());
}
This could compile, but looks like it's not behaving correctly.
It always executes both branches, for e.g. when recordA isPresent(), it still executes recordB.get().getCreatedAt() which throws me
java.util.NoSuchElementException: No value present
Any help is appreciated!
Basically, I'd like to replace the traditional ternary operator with more advanced Optional/lamda features.
To avoid eagerly evaluating else-branches, use orElseGet, which takes an instance of the functional interface Supplier:
return recordA.map(
record -> record.getCreatedAt())
.orElseGet(() -> recordB.get().getCreatedAt());
You're looking for .orElseGet(() -> recordB.get().getCreatedAt()); and the reason to that can be found on this post --> Difference between Optional.orElse() and Optional.orElseGet()
Some people may find it a bit subjective but personally, I'd say by default, it makes more sense to use orElseGet() as opposed to orElse every time except in the case where the default object is already constructed as this will prevent many unexpected problems (given you didn't read the differences between orElse and orElseGet doc) as such of the one you're facing now.
read more from Java Optional – orElse() vs orElseGet()
My question about recordB being Optional got unanswered but if it is Optional then you cannot just safely call its get method, you need to check if it is empty or not. Here safe call to get record or null if both recordA and recordB are empty Otionals.
recordA
.map(Record::getCreatedAt)
.orElseGet( () -> recordB.map(Record::getCreatedAt).orElse(null) );
If you are using Java 9+, you may be able to use ifPresentOrElse() method as more completely explained in this Stackoverflow answer.
recordA.ifPresentOrElse(
value -> recordA.get().getCreatedAt(),
() -> recordB.get().getCreatedAt()
);
This question already has answers here:
Java: avoid checking for null in nested classes (Deep Null checking)
(13 answers)
Closed 4 years ago.
I need a generic way for null check. I came up with a requirement.
This is my setter method for a class:
placeHolderValues.setCurrentAddressCountry(communicationSO.getApplicationDetailSO().getApplicantDetails().get(0).getAddressDetail().get(0).getCountry());
I want to set values in placeHolderValues.setCurrentAddressCountry() only when value is present. If any of the getApplicationDetailSO() or getApplicantDetails() or getAddressDetail() or getCountry() is NULL then I have to set NULL in placeHolderValues.setCurrentAddressCountry(). I have almost 30 such types of setter.
I need a common method to achieve the same.
A serious non-answer here: don't do it that way.
Using getA().getB().getC().getD()...getTheThingYouWant() is really bad practice.
It is a clear violation of the Law Of Demeter.
So besides the problem you run into (about checking null), such constructs are really actually evil. You see, the class using this code must know that an A has a B. And that B has a C. And so on. This directly couples this class with all classes A, B, C, ... and so on.
The real answer is to avoid such changing. If at all, you do getA().getMeWhatINeed().
The only other alternative: validate your input data completely (in an upfront step), before going down such call chains.
You could use Optional.ofNullable and repeatedly map the value into another, unless you encouter null on the way, and then get the final value orElse null.
var value = Optional.ofNullable(communicationSO)
.map(x -> x.getApplicationDetailSO())
.map(x -> x.getApplicantDetails())
.map(x -> x.get(0))
.map(x -> x.getAddressDetail())
.map(x -> x.get(0))
.map(x -> x.getCountry())
.orElse(null);
placeHolderValues.setCurrentAddressCountry(value);
This still is not very pretty, but at least you do not have to repeat the different method calls. Some of those lambdas (->) could probably also be replaced with proper Method references. (::) Still, it's probably better than just wrapping the line into a try block and catching the NullPointerExceptoin.
In Java 8,
I currently have a lambda that looks like this:
.createSomething((acceptableStates, someProxy) -> (userId) ->
acceptableStates.contains(someProxy.getSomeAttributeId(userId)))
However, we have changed someProxy.getSomeAttributeId to return an Optional<String> instead of a string.
What's the cleanest / most accepted way to essentially check for if acceptableStates contains the value of someProxy.getSomeAttributeId(userId) if the attribute returned isn't empty?
(Note: acceptableStates is still a list of strings, not of Optional<String>)
.... userId -> someProxy.getSomeAttributeId(userId)
.map(acceptableStates::contains)
.orElse(Boolean.FALSE);
Unfortunately, I see no very clean solution here. Refer to this question: Functional style of Java 8's Optional.ifPresent and if-not-Present?
Additionally, you even have to save the optional in a variable if the call to getSomeAttributeId does cost resources.
.createSomething((acceptableIds, someProxy) -> (userId) ->
{
Optional<String> attrId = someProxy.getSomeAttributeId(userId);
return attrId.isPresent() ? acceptableStates.contains(attrId.get()) : false;
})
I strongly recommend writing understandable and clear code like this snippet:
Optional<SomeAttributeId> optional = someProxy.getSomeAttributeId(userId);
return optional.isPresent() && acceptableStates.contains(optional.get());
If there should not be thrown an exception (1) when someProxy.getSomeAttributeId(userId) is an empty optional:
acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElseThrow(() -> new Exception()))
Or unless you have the default value (2) to fill up the result with:
acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElse(DEFAUT_VALUE))
My point:
Do not pursue Java 8 features which will mess everything up, especially in cases where a simple boolean expression could be used. I had experience refactoring some code toward plain Java statements because new people (1.1) came in a project could not get what the code does. With the time, even I (as a writer) barely can do so (1.2).
Also, with that "lambda chain" style, one slight change could cause rewriting a snippet/method entirely (2).
It is always fun to poke around n-nested lambdas, where n > 2 (3).
Anyway, if you don't share my point, #Eugene proposed a good way to go with.
return value.isPresent() && value.get().contains("some-text");
I'm looking for a more convenient way of proofing equality for an Optional value.
This is what an Oracle Blog post suggests:
Optional<USB> maybeUSB = ...;
maybeUSB.filter(usb -> "3.0".equals(usb.getVersion())
.ifPresent(() -> System.out.println("ok"));
IMHO results in something like
if (maybeUSB.filter(c -> "3.0".equals(c.getVersion())).isPresent()) {
...
}
Of course that's kind of a poor example because it compares the Version and not the instance of USB itself but I think it should still proof my point.
Is this really as good as it gets?
No
boolean presentAndEquals(Object)
or
boolean deepEquals(Object)
Am I missing something here?
EDIT:
I'm not that happy with Optionals.equals either.
Do I really have to box an Object first to instantly unbox and check for equality ?
EDIT II:
Pretty damn happy with:
optional
.filter(nonOptional::equals)
.isPresent()
nowadays.
After some years of functional programming, if looses a lot of relevance.
You have many options.
Already noted:
boolean isEqual = maybeFoo.equals(Optional.of(testFoo));
Alternatively:
boolean isEqual = maybeFoo.isPresent() && maybeFoo.get().equals(testFoo);
Or:
boolean isEqual = testFoo.equals(maybeFoo.orElse(null));
These last two do have slightly different semantics: each returns a different value when maybeFoo is empty and testFoo is null. It's not clear which is the correct response (which I guess is one reason there's not a standard API method that does this).
You can probably come up with others if you read the Optional API doc and apply some thought. There's nothing magic that's absent from the docs.
More generally, if you're knocking against this often enough for it to bother you, you might be approaching Optional with the wrong philosophy.
As I see it, Optional is about acknowledging that something won't always be present, and that you need (sometimes verbose) code to handle that.
This should be the exception. Wherever possible, try and create variables that can't be null or Optional.empty().
In situations where this is unavoidable, embrace the fact that you need extra code.
Optional implements the equals method directly:
if (maybeUSB.equals(Optional.ofNullable(testUSB))) {
...
}
(you can also use Objects.equals rather than calling equals directly)
EDIT:
If you want both not present to be false, you can do this:
if (maybeUSB.equals(Optional.ofNullable(testUSB)) && maybeUSB.isPresent()) {
...
}
Would this work?
if (maybeUSB.map(c -> c.getVersion().equals("3.0")).orElse(false))