Right.
public static Optional<String> getFileMd5(String filePath)
throws NoSuchAlgorithmException, IOException {
return Optional.empty(); // I.o. null
return Optional.of(nonnullString);
}
Usage:
getFileMd5(filePath).ifPresent((s) -> { ... });
or (less nice as undoing the Optional)
String s = getFileMd5(filePath).orElse("" /* null */);
Answer from Joop Eggen on Stack OverflowVideos
My service layer has a method which return an Optional of an object by the id.
My question is what the better practice, when the object is not found
· Throw an exception.
· Return empty Optional.
I tend toward returning an empty Optional since I see no reason to use Optional in the first place if I intend the method to throw exception.
Anyway I would like to hear your opinion on the subject.
I've been reading about this topic for a while, and there seems to be different trains of thought.
If you watch the presentation by Goetz and Stuart Marks about the Java 8 features, it seems that they are against Optional being used this way.
Goetz even makes a comment about it here: https://stackoverflow.com/a/26328555
However, if you look at other stackoverflow answers or even reddit threads (like https://www.reddit.com/r/java/comments/6h91ms/method_return_optional_or_null/), you'll notice that a lot of people do support return Optional for a getter.
So now that this Optional API has been in place for a while, what are the recommendations for it? How have you been using it?
It depends.
A class List can have a method firstElement which should return an Optional to indicate there may be no elements.
A data or value class like eg class User with name and birthdate should use constructor injection that enforces all attributes are provided and are not null. Then there's no need to wrap anything in Optional.
Since there are a lot more pitfalls to take into account when it comes to data or value classes, it makes sense to use Google Immutables to have them generated for you according to best practices so you only have to worry about what attributes they should have and not how they should work.
If you find yourself adding Optional attributes to data or value classes, eg Optional memberNumber to the User class, you're probably doing something wrong. Instead, create a Member class that has a user and a memberNumber.
I don't know if it was necessarily ever considered a good practice, but is one that some developers have adopted. I, myself, mainly use Optional with the Stream API, which seems to be why it was created in the first place.
Aside from having to unwrap another object just to get to your data, I just think a return type Optional<Point> creates a lot more unnecessary visual noise than just Point.
Optional, though, may become more main stream when value types arrive on the scene, seeing that they are not nullable.
Actually what you are searching is: Optional.map. Your code would then look like:
Copyobject.map(o -> "result" /* or your function */)
.orElseThrow(MyCustomException::new);
I would rather omit passing the Optional if you can. In the end you gain nothing using an Optional here. A slightly other variant:
Copypublic String getString(Object yourObject) {
if (Objects.isNull(yourObject)) { // or use requireNonNull instead if NullPointerException suffices
throw new MyCustomException();
}
String result = ...
// your string mapping function
return result;
}
If you already have the Optional-object due to another call, I would still recommend you to use the map-method, instead of isPresent, etc. for the single reason, that I find it more readable (clearly a subjective decision ;-)).
Two options here:
Replace ifPresent with map and use Function instead of Consumer
Copyprivate String getStringIfObjectIsPresent(Optional<Object> object) {
return object
.map(obj -> {
String result = "result";
//some logic with result and return it
return result;
})
.orElseThrow(MyCustomException::new);
}
Use isPresent:
Copyprivate String getStringIfObjectIsPresent(Optional<Object> object) {
if (object.isPresent()) {
String result = "result";
//some logic with result and return it
return result;
} else {
throw new MyCustomException();
}
}