The billion dollar mistake has been committed already. No going back. But it is not necessary to keep repeating it. Oh, I am talking about the infamous null.
A real solution to avert the issues surrounding null is to completely avoid using it in your code, and replace direct use of null with some sort of nullable container, such as the Option[A] in Scala. You could go even as far and enforce not to use null anywhere in your code via Scalastyle or other linters.
In Scala, it is pretty common to pass and return1 Option. For instance …
case class Email(
subject: String,
body: String,
attachment: Option[Attachment]
)
object Email {
def apply(subject: String, body: String): Email =
new Email(subject, string, attachment = None)
}
In the above code, attachment may optionally be passed to create an instance of Email. Another way, a bad one, to achieve the same with sufficient safety around null is:
// This is bad! Don't do it!
class Email(
val subject: String,
val body: String,
attached: Attachment
) {
val attachment: Option[Attachment] = Option(attached)
}
// calling code
new Email("hello", "world", null)
The above code does not use Option but directly use null, which is wrapped with an Option inside the Email class. While this provides safety net around null, it is just a bad way.
Introducing null in one place potentially causes loss in the strictness of types. The null may be direct value as shown in the example above. Or a runtime value passed down via chain of calls to a variable passed to Email constructor, which makes it harder to reason about. Besides, did you notice I had to change the original case class to a regular class2?
Let us switch gears. Java too has a nullable container - the infamous3 Optional<T>.
In the Java realm, returning Optional from methods is acceptable. Passing Optional as parameters is not.
IntelliJ warns such cases via its inspections.

While you can suppress inspections at your will, that is the not point. It is recommended not to pass Optional as parameters. Even by Java experts.

I was not able to find a compelling reason behind such a recommendation, which is in contrast to Scala. Almost every link or material I came across was about to disabling4 the inspection to silence IntelliJ from throwing the warning.
However, I came across a couple of things where were better out of the lot. But not compelling.
- In the case when there are multiple
Optionalparameters, the calling code would look clumsy. Meh! Real production Java code is ugly 🤷♂️ because Java syntax is verbose and noisy. I don’t buy that multipleOptionalparameters is going to make uglier. - Using
Optionalparameters introduces conditional logic in the method. Of course, it should. Wouldn’t there be conditional logic or guards if we were dealing withnullinstead ofOptional? OnlyOptionalmakes it disciplined. You wouldn’t use the parameter in question blindly without null check, would you? Optionalis relatively expensive. This is a hard sell unless one can prove thatOptionalin the particular case is the bottleneck. In the grand scheme of things, the cost ofOptionalshould be negligible. Unless it can be proven it is not negligible.- … although I buy the point here. If you are using
Optional, typically you would use its methods that takes lambdas or such, which drags in some extra allocations. Again, should not be a problem unless it is proven to be a problem.
- … although I buy the point here. If you are using
- Finally, what if
nullitself is passed the value for theOptionalparameter? Duh! I am not denying this is a legit case although I see this as a problem of culture.- In Scala and other functional languages, there is a clear distinction in practice and convention between
nullandOption. I am yet to encounter a case where a piece of code dealing withOptionreceived anull. For that matter, I am yet to come across code that was working with aStringand encounterednull. If aStringwere to be optional, it would have been anOption[String]. Validations at the highest levels may even wrap empty or blankStrings into aNone; depending on the case. I thought I would say that the above is practiced religiously. But no. It is just how Scala programmers, and generally speaking functional programmers think about it. It is sadly not the case with Java; at least mainstream5.
- In Scala and other functional languages, there is a clear distinction in practice and convention between
On a larger scale, I prefer to align with the community - practices, guidelines and conventions. And temper only specific things to cater to my taste/style. For a good reason. In the case of this warning about using Optional parameters, I have mixed feelings. Neither do I want to disable the inspection in IntelliJ because IntelliJ team is way smarter than us, and I hope they added it for a reason. Nor do I want litter my code with SuppressWarnings4.
Given that the IntelliJ inspection is a tooling aspect and general advice from elders, I might consider disabling it after all.
-
The
case classfields are getters and hence are returningOption. The constructor as written above is the argument. So, passing and returning. ↩︎ -
Similar handling is not possible using
case class; at least not in a clean way. You might end up having redundant fields breaking invariant onattachment. Or some unnecessarily convoluted code. ↩︎ -
Yes, infamous. Because it is poorly implemented. I might have to write about it in separate post. Let me not digress. ↩︎
-
In the worst case you have to suppress the warning, use
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")instead of disabling the inspection for all cases. ↩︎ ↩︎ -
There are definitely some elite / esoteric Java code out there that fall in the category of functional thinking, if not really written using functional techniques. ↩︎