I found implemented this code (method where this part of code is used is returning Optional<File>, this part of code had to be added for verification if values are correct and case can be saved):
if (!CaseChecker.checkValues(case)) {
return Optional.of(new File("FALSE"));
}
When I asked the person, why he is returning something like this. The answer was "Optional can contain any value". To be honest I don't agree with this, because type of Optional is for some reason. So I wanted to confirm if Optional can be really anything and if yes, then what's the reason to write Optional type.
The whole point of Optional is to avoid the situation where you return a bogus value (like null, or like returning -1 from String.indexOf in order to indicate it didn't find anything), putting the responsibility on the caller to know what is bogus and to know to check for it. Returning Optional lets the caller know it needs to check whether a valid result came back, and it takes away the burden of the caller code needing to know what return values aren't valid.
Optional was never meant as a wrapper for a bogus value.
And yes you can return anything. The api doesn't stop you from doing nonsensical things.
Also consider that flatMap doesn't know what to do with this weird thing, it will treat the contents as nonempty. So now how you can use this value is limited. You have a multistage validation process where it might be something you can handle with operations chained together using flatMap, but this fake file has made that harder. It's limited your options.
Return Optional.empty() if you don't have a valid value to return.
Related
First of all, I know the difference between the two methods.
Optional.of : Used to ensure that there is no null, if null is entered, nullPointExcepction
Optional.ofNullable : may or may not be null. Used to respond flexibly.
So, if I add orElseThrow(() -> new NullPointerException("null data")) to this, will it end up being the same?
I want to throw an error with explicit content.
So I get Optional.ofNullable(data).orElseThrow(() -> new NullPointerException("null data")))
use it as Is this pointless behaviour?
Optional.of(data).orElseThrow(() -> new NullPointerException("null data")))
I think this is also possible, but I'm just using ofNullable() to make the code look consistent.
to sum it up,
In the end, if you add orElseThrow(nullPoint)
Are of or ofNullable the same result?
then rather
Is of.orElseThrow better?
to sum it up, In the end, if you add orElseThrow(nullPoint) Are of or ofNullable the same result?
No. To see this, simply look at the types.
public static <T> Optional<T> of(T value);
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
throws X extends Throwable;
Optional.of returns an Optional<T>, where orElseThrow is going to leave you with a T. So Optional.ofNullable(x).orElseThrow(...) is really just a very roundabout
if (x == null) {
throw new NullPointerException(...);
}
You're not actually doing anything with the Optional, just making one and discarding it in a really verbose way. So if that's your intent, just do an explicit null check; there's no need at all for Optional.
Which raises the question of why we would use of or ofNullable. With the introduction of Optional, there are now two ways to represent the concept of "this value might not exist" in Java: null and Optional.empty(). People on the Internet will argue till the end of time about which is better and when you should use which one (I have strong opinions on this which I'll refrain from sharing here, since it's not what you asked), but the point is that there are two different ways to do it.
For the rest of this post, I'll borrow a bit of notation from Kotlin and write T? to mean "a T value which might be null". It's not valid Java notation, but it gets the point across. So if we want to represent "A T which may or may not exist" in Java, we can use either Optional<T> or T?.
If we want to go from T? to Optional<T>, that's what Optional.ofNullable is for. It says "If the thing is null, give me Optional.empty(); otherwise give me the thing in an Optional". To go the other way, we can use Optional.orElse(null), which says "If I have a T, give it to me, otherwise show me null". So now we have a way to convert between the two approaches. So what's Optional.of for?
You should view Optional.of as an assertion of sorts. If Java had nullable types like Kotlin, then the difference would be something like
public static <T> Optional<T> of(T value);
public static <T> Optional<T> ofNullable(T? value);
That is, ofNullable expects that its value might be null. of is already assuming that it's not. Optional.of should be thought of an assertion that the value you're giving it is not null. If that assertion fails, we throw NullPointerException immediately rather than letting errors propagate to other parts of the program. If you're calling Optional.of and recovering from the NullPointerException it throws[1], then you are doing something very wrong. That function is an assertion we were dealing with non-null data to begin with, and if that assertion fails then your program should fail immediately with a good stack trace.
It sounds like, based on your use case, you have a value that might be null. In that case, Optional.ofNullable makes sense; it's prepared to handle the use case. If you want to throw a custom exception, you should do a null check beforehand (since you're the one handling the null, not Optional) and then call Optional.of. Or, of course, you can just do an old-fashioned null check and not use Optional at all, if you're planning to extract it anyway with orElseThrow. Certainly, the pipeline Optional.ofNullable(value).orElseThrow(...) in one line would be a code smell.
[1] Note that I say "recovering from", not "catching". A nice top-level catch (Exception exc) which logs all errors is perfectly acceptable and generally a good idea in larger applications. But if you're doing catch (NullPointerException exc) { return 0; } or something like that then you need to reconsider which Optional method you should be using.
First of all, I know the difference between the two methods.
Optional.of : Used to ensure that there is no null, if null is
entered, nullPointExcepction
Optional.ofNullable : may or may not be null. Used to respond
flexibly.
There's a clear point of misunderstanding.
The purpose of Optional.of() is not "to ensure that there is no null". It is not meant to be used as an assertion that a value that was passed into it is non-null. For such a validation you can use Objects.requireNonNull(), it'll either throw an NPE, or will return you a non-null value.
In order to be on the same page, the first important thing you have to keep in mind is that optionals were introduced in the JDK for only one particular purpose - to serve as a return type. Any other cases when optional is utilized as a parameter-type, or a field-type, or when optional objects are being stored in a collection isn't considered to be a good practice. As well, as creating an optional just in order to chain methods on it or to hide a null-check is considered to be an antipattern.
Here is a couple of quotes from the answer by #StuartMarks, developer of the JDK:
The primary use of Optional is as follows:
Optional is intended to
provide a limited mechanism for library method return types where
there is a clear need to represent "no result," and where using null
for that is overwhelmingly likely to cause errors.
A typical code smell is, instead of the code using method chaining to
handle an Optional returned from some method, it creates an Optional
from something that's nullable, in order to chain methods and avoid
conditionals.
I also suggest you to have a look at this answer to the question "Should Optional.ofNullable() be used for null check?", also by Stuart Marks.
With all that being said, combination Optional.of().orElseThrow() is both wrong and pointless:
If provided data is null method of() will raise an NPE and orElseThrow() will not be executed (i.e. its exception will get never be fired).
You're abusing the optional by creating an optional object not in order to return a nullable variable wrapped by it, but to hide the null-check (take a look at the quote above). That obscures the purpose of your code. You can use Objects.requireNonNull() instead to throw an exception if the given value must not be null or requireNonNullElse() to provide a default value.
For the same reason, you shouldn't use Optional.ofNullable().orElseThrow() at the first place.
Optional is like a Box
You might think of optional is if it is a parcel. When you need to send something, you go to the post office (i.e. returning from the method), where the thing that has to be sent is being placed into a box. When somebody (i.e. the caller) receives the parcel, it is being immediately unpacked. That is the whole lifecycle of the box called Optional.
When, according to the logic of your application, an object required to be returned from the method should not be null - use Optional.of(). It'll either send a parcel successfully or will emphasize that there's a problem by raising a NullPointerException.
If the given object is nullable by its nature, i.e. null isn't an abnormal case, then use Optional.ofNullable(), it'll fire either a box containing the object or an empty box.
And the caller (i.e. method that invokes the method returning an optional) is the one who has to unpack the box using a variety of tools that optional provides like orElseThrow(), orElseGet(), ifPresent(), etc.
I'm attempting to understand what's happening in this bit of Java code as its owner are no longer around and possibly fixing it or simplifying it. I'm guessing these blocks had a lot more in them at some point and what's left in place was not cleaned up properly.
It seems all occurrences of orElse(false) don't set anything to false and can be removed.
Then the second removeDiscontinued method is returning a boolean that I don't think is used anywhere. Is this just me or this is written in a way that makes it hard to read?
I'm hesitant removing anything from it since I haven't used much of the syntax like orElse, Lazy, Optional. Some help would be much appreciated.
private void removeDiscontinued(Optional<Map<String, JSONArrayCache>> dptCache, Lazy<Set<String>> availableTps) {
dptCache.map(pubDpt -> removeDiscontinued(pubDpt.keySet(), availableTps)).orElse(false);
}
private boolean removeDiscontinued(Set<String> idList, Lazy<Set<String>> availableTps) {
if (availableTps.get().size() > 0) {
Optional.ofNullable(idList).map(trIds -> trIds.removeIf(id -> !availableTps.get().contains(id)))
.orElse(false);
}
return true;
}
This code is indeed extremely silly. I know why - there's a somewhat common, extremely misguided movement around. This movement makes claims that are generally interpreted as 'write it 'functional' and then it is just better'.
That interpretation is obvious horse exhaust. It's just not true.
We can hold a debate on who is to blame for this - is it folks hearing the arguments / reading the blogposts and drawing the wrong conclusions, or is it the 'functional fanfolks' fanning the flames, so to speak, making ridiculous claims that do not hold up?
Point is: This code is using functional style when it is utterly inappropriate to do so and it has turned into a right mess as a result. The code is definitely bad; the author of this code is not a great programmer, but perhaps most of the blame goes to the functional evangelistst. At any rate, it's very difficult to read; no wonder you're having a hard time figuring out what this stuff does.
The fundamental issue
The fundamental issue is that this functional style strongly likes being a side-effect free process: You start with some data, then the functional pipeline (a chain of stream map, orElse, etc operations) produces some new result, and then you do something with that. Nothing within the pipeline should be changing anything, it's just all in service of calculating new things.
Both of your methods fail to do so properly - the return value of the 'pipeline' is ignored in both of them, it's all about the side effects.
You don't want this: The primary point of the pipelines is that they can skip steps, and will aggressively do so if they think they can, and the pipeline assumes no side-effects, so it makes wrong calls.
That orElse is not actually optional - it doesn't seem to do anything, except: It forces the pipeline to run, except the spec doesn't quite guarantee that it will, so this code is in that sense flat out broken, too.
These methods also take in Optional as an argument type which is completely wrong. Optional is okay as a return value for a functional pipeline (such as Stream's own max() etc methods). It's debatable as a return value anywhere else, and it's flat out silly and a style error so bad you should configure your linter to aggressively flag it as not suitable for production code if they show up in a field declaration or as a method argument.
So get rid of that too.
Let's break down what these methods do
Both of them will call map on an Optional. An optional is either 'NONE', which is like null (as in, there is no value), or it is a SOME, which means there is exactly one value.
Both of your methods invoke map on an optional. This operation more or less boils down, in these specific methods, as:
If the optional is NONE, do nothing, silently. Otherwise, perform the operation in the parens.
Thus, to get rid of the Optional in the argument of your first method, just remove that, and then update the calling code so that it decides what to do in case of no value, instead of this pair of methods (which decided: If passing in an optional.NONE, silently do nothing. "Silently do nothing" is an extremely stupid default behaviour mode, which is a large part of why Optional is not great). Clearly it has an Optional from somewhere - either it made it (with e.g. Optional.ofNullable in which case undo that too, or it got one from elsewhere, for example because it does a stream operation and that returned an optional, in which case, replace:
Optional<Map<String, JSONArrayCache>> optional = ...;
removeDiscontinued(thatOptionalThing, availableTps);
with:
optional.map(v -> removeDiscontinued(v, availableTps));
or perhaps simply:
if (optional.isPresent()) {
removeDiscontinued(optional.get(), availableTps);
} else {
code to run otherwise
}
If you don't see how it could be null, great! Optional is significantly worse than NullPointerException in many cases, and so it is here as well: You do NOT want your code to silently do nothing when some value is absent in a place where the programmer of said code wasn't aware of that possibility - an exception is vastly superior: You then know there is a problem, and the exception tells you where. In contrast to the 'silently do not do anything' approach, where it's much harder to tell something is off, and once you realize something is off, you have no idea where to look. Takes literally hundreds of times longer to find the problem.
Thus, then just go with:
removeDiscontinued(thatOptionalThing.get(), availableTps);
which will NPE if the unexpected happens, which is good.
The methods themselves
Get rid of those pipelines, functional is not the right approach here, as you're only interested in the side effects:
private void removeDiscontinued(Map<String, JSONArrayCache> dptCache, Lazy<Set<String>> availableTps) {
Set<String> keys = dptCache.keySet();
if (availableTps.get().size() > 0) {
keys.removeIf(id -> availableTps.get().contains(id));
}
}
That's it - that's all you need, that's what that code does in a very weird, sloppy, borderline broken way.
Specifically:
That boolean return value is just a red herring - the author needed that code to return something so that they could use it as argument in their map operation. The value is completely meaningless. If a styleguide that promises: "Your code will be better if you write it using this style" ends up with extremely confusing pointless variables whose values are irrelevant, get rid of the style guide, I think.
The ofNullable wrap is pointless: That method is private and its only caller cannot possibly pass null there, unless dptCache is an instance of some bizarro broken implementation of the Map interface that deigns to return null when its keySet() method is invoked: If that's happening, definitely fix the problem at the source, don't work around it in your codebase, no sane java reader would expect .keySet to return null there. That ofNullable is just making this stuff hard to read, it doesn't do anything here.
Note that the if (availableTps.get().size() > 0) check is just an optimization. You can leave it out if you want. That optimization isn't going to have any impact unless that dptCache object is a large map (thousands of keys at least).
What do you think is better (with arguments, of course):
Optional.ofNullable( userName )
.ifPresent( nonNullUserName -> header.setUser( createUser( nonNullUserName ) ) );
or
header.setUser( userName == null ? createUser( userName ) : null );
The method createUser creates xml element and the intent of the whole peace of code is to set it in a SOAP request depending on presence of userName.
The benefits of the first approach I see is the absence of useless operations, the code does one thing and no more. But the second approach lets you save one more line of code thus appearing to be more laconic.
UPDATE: I guess I missed a thing I actually implied and it caused certain misunderstanding. It would be better to provide cleaner examples with explanations if you have some.
Optional was designed to be used as a return type for methods that can't always return a value, like for example getFirstElementOfAList(), which can't return anything else if the list is empty: returning null would be less clear than returning an empty Optional, and could mean that the first element is null, and not that there is no first element.
The designers don't intend Optional to be used as a convenience construct to chain methods. See the presentation by Stuart Marks (who works on the JDK), and especially what he says at the 28th minute:
It's generally a bad idea to create an Optional for the specific purpose of chaining methods [...]
You're of course free to disrespect the intended design and the best practices, but your colleagues might also be free to hate you for that :-)
Note that the two snippets you posted don't do the same thing. The first one does nothing if the user name is null, whereas the second one sets the user to null (which might in turn throw an exception or overwrite the previous value)
I would just use (assuming what you want is the first version):
if (userName != null) {
header.setUser(createUser(userName));
}
which is extremely clear, doesn't abuse Optional, and doesn't create an Optional instance just to chain methods.
They are different things, one is an Object, another is an operator. you shouldn't comparing between them. the first approach can be simplified to this, which will be more readable & descriablable:
Optional.ofNullable(userName).map(this::createUser).ifPresent(header::setUser);
IF you really want to comparing between them, the only one different is you have been mentioned above. and if you process condition or result more complex in an operator that will result to the expression is too complex to read.
Assume I have a Java method
public X findX(...)
which tries to find an Object of type X fulfilling some conditions (given in the parameters). Often such functions cannot guarantee to find such an object. I can think of different ways to deal with this:
One could write an public boolean existsX(...) method with the same signature which should be called first. This avoids any kind of exceptions and null handling, but probably you get some duplicate logic.
One could just return null (and explain this in javadoc). The caller has to handle it.
One could throw a checked exception (which one would fit for this?).
What would you suggest?
The new Java 8 Optional class was made for this purpose.
If the object exists then you return Optional.of(x) where x is the object, if it doesn't then return Optional.empty(). You can check if an Optional has an object present by using the isPresent() method and you can get the object using get().
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
If you can't use Optional I would go with option 2.
In the case of 1. You'd be doing double work, first you have to check if X exists, but if it does, you're basically discarding the result, and you have to do the work again in findX. Although the result of existsX could be cached and checked first when calling findX, this would still be an extra step over just returning X.
In the case of 3. To me this comes down to usability. Sometimes you just know that findX will return a result (and if it doesn't, there is a mistake somewhere else), but with a checked exception, you would still have to write the try and (most likely empty) catch block.
So option 2 is the winner to me. It doesn't do extra work, and checking the result is optional. As long as you document the null return, there should be no problems.
Guava (potentially other libraries, too) also offers an Optional class that might be worth exploring if your project uses Guava since you seem to not use Java 8.
If you
don't/can't/won't use Java 8 and its accompanying Optional type
don't want another library dependency (like Guava) for a single class implementation
but
you want something more robust than methods that can return null for which you have to have a check in all consumers (which was the standard before Java 8)
then writing your own Optional as an util class is the easiest option.
This is probably more a question about functional programming than about Java 8 specifically, but it's what I'm using right now.
I have a source object (could represent a repository, or a session..., doesn't matter here) that has a method retrieveSomething() that returns an Optional<SomethingA>.
I have a method somewhere that returns a Something, by calling retrieveSomething() and providing a default value in case the optional was empty, as follows:
return source.retrieveSomething()
.orElseGet(() -> provideDefaultValue());
Now I want to modify this code so that in case the source didn't contain any value yet (so the optional was empty), the source is updated with the provided default value.
Of course, I could easily do that inside a lambda expression code block:
return source.retrieveSomething()
.orElseGet(() -> {
Something sth = provideDefaultValue()
source.putSomething(sth);
return sth;
});
But if I understand correctly, I'm not supposed to use functions that cause side effects. So what's the "correct" (functional) way to do this, keeping the benefit of using Optional (in real code I'm actually also performing a map operation on it, but that's irrelevant here) ?
You could follow the way Java does this with Map.computeIfAbsent()
which takes a second parameter which is a function on how to compute and insert the record:
So your code would become:
Something something = source.computeIfAbsent(sth, (k)->provideDefaultValue());
An advantage of using a lambda to compute the default instead of just passing it in, is the lambda will only be evaluated if it needs to be so if computing the default is expensive, you only have to pay it when you need it.
From a conceptual standpoint, you use the optional pattern to deal with the absence of a return value. This means, if your source instance doesn't contain a value for you to use, you have the choice of providing a default value to use in its place.
It is not advised to modify the Optional directly to provide its value; that instance may be temporal and will differ on subsequent calls to retrieve it.
Since a function call truly governs what's returned by that Optional, the only approach you have if you truly want to go down this route is to modify how that value is computed. This really should be done from within the function providing the Optional, but it could be done outside of it if necessary.
Since there's not enough code structure here to truly write up some example, I will describe the steps:
Outside of the method providing the Optional, you write the same closure as you did before, with the side effect of adjusting the value used to compute the original Optional. This is likely a field of some sort.
Inside of the method providing the Optional, you ensure that you don't expose provideDefaultValue anywhere else (since they won't need it), and use a boolean conditional before you package the Optional.
return value == null ? Optional.of(provideDefaultValue()) : Optional.of(value);
...but that really defeats the purpose of the Optional, as you're still doing a null check.
A slightly better approach to the above would be to compute value in such a way that it was either itself or the default value, and return the Optional of that...
value = computeValue();
if(null == value) {
value = provideDefaultValue();
}
return Optional.of(value);
...but again, seriously defeating the purpose of Optional, as you're doing null checks.
An answer I came up with myself, which I'm not entirely satisfied with, but may serve as an example of what I'm looking for:
I could implement something similar to a Pair<V1,V2> class and then map the Optional<Something> to a Pair<Something, Boolean> where the Boolean value would indicate whether or not the value was a generated default:
Pair<Something, Boolean> somethingMaybeDefault =
source.retrieveSomething()
.map(sth -> new Pair<Something, Boolean>(sth, false))
.orElseGet(() -> new Pair<Something, Boolean>(provideDefaultValue(), true));
Then I'd update in case the boolean is false:
if (somethingMaybeDefault.value2()) {
source.putSomething(somethingMaybeDefault.value1());
}
And finally return the new value:
return somethingMaybeDefault.value1();
Of course, this uses imperative style for the update, but at least the functions remain pure.
I'm not sure this is the best possible answer though.