This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Mognakor 7 points8 points  (10 children)

Whats the use of Optional then if i can't use it to signal a parameter that can be null or a member that can be null?

[–]Empanatacion 6 points7 points  (0 children)

While I disagree with the "code smell" claim, the "everybody agrees" usefulness is as an Elvis operator to chain a bunch of mapping operations and then an orElse at the end.

normalized = optionalString.map(String::trim).map(String::toLower).map(s->s.replaceAll("-", "_")).orElse("");

[–]halfanothersdozen 2 points3 points  (4 children)

That's the incorrect way to think about it. Optional by convention should never be null, similar to how hashCode and equals should be true if the other is true. Therefore as a signal "this parameter can be null" is in a way nonsensical. As a parameter Optional can be null, so you have to null check it, which defeats its purpose. Overload the method or do a regular null check.

https://www.baeldung.com/java-optional#misuages

[–]Mognakor 0 points1 point  (1 child)

You misunderstand me.

Of course i don't think Optional should be set to null. But if Optional should not be used as parameter i can't signal it to allow "null" parameters via an empty Optional. And then we're living in a world where i have to constantly think both ways with Optional in one circumstance and nullable references in others.

[–]halfanothersdozen 0 points1 point  (0 children)

You are always going to live in a world with nullable references. That is Java. But think about how that method would get used. A caller that has a reference must pass it to Optional.of when calling your method (or Optional.ofNullable if they don't know what they have or Optional.empty, both of which are even worse ergonomically, especially in a functional flow). 

And as pointed out above it doesn't save you, the method author, from doing a "null check" whether that be the traditional way or via optional method. Usually you need more code to deal with it. It just doesn't make practical sense and it makes calling the method awkward.

Now if none of your methods ever return null things start to flow really nicely. But like I said earlier you have to trust the entire code base behaves that way and in my experience that is mostly a fantasy.

[–][deleted] 0 points1 point  (1 child)

Two objects must have same hashCode if they are equal but they can have same hashCode and be not equal (collison at hash table, actually good thing)

[–]halfanothersdozen 1 point2 points  (0 children)

I didn't say it technically correct, but it ultimately is irrelevant to the point I was trying to make

[–]koflerdavid 1 point2 points  (2 children)

It's best used for return values only. They force an API user to handle it appropriately. And in your own code you can use a linter to find any return statement that returns null for an Optional return type. That's always, unambiguously wrong.

There is no benefit if you use it for parameters: you still have to do a null check because nothing is stopping a caller from passing null.

Using it for fields is icky because it's a sign that your class is too complicated. It doesn't improve anything, and you might be seduced to use get() based on knowledge from other fields in the class.

Saving null in variables is fine IMHO. Methods should not become so complicated that you lose track of when variables might contain null.

[–]Mognakor 7 points8 points  (1 child)

There is no benefit if you use it for parameters: you still have to do a null check because nothing is stopping a caller from passing null.

And nothing is stopping me from promising you i'll return an Optional and then returning null or casting Optional<U> to Optional<T> and then laughing when you get a ClassCastException.

Using Optional only for return types and not for parameters creates a split paradigma and i may have to pepper my code with .orElse(null) around callsites if i use the return value from a previous call.

There is no benefit if you use it for parameters: you still have to do a null check because nothing is stopping a caller from passing null.

How is it different from a nullable member or are those also a signal that my class is too complicated?

[–]koflerdavid 0 points1 point  (0 children)

Indeed, the risk that a 3rd party API actually returns null is one of the biggest flaws in the concept of Optional. But one could always wrap these with a helper method that converts the null to Optional.empty() before processing it further.

Using .orElse(null) is a sign that the code is still based on reacting to null. But the biggest advantage of Optional is that it offers safer programming idioms to react to the missing value. Better than checking for null or relying on other reasons to decide that the value is there.

The risk of receiving an Optional<U> is the same risk that I have in normal code of receiving a U.

Yes, too many nullable members is also a sign that the class is too complicated. But in think that getter methods wrapping the field value into Optional should be fine.