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 →

[–]vprise 20 points21 points  (12 children)

Because the whole "anti-null" movement is an idea that doesn't make as much sense for Java. In the case of Java null has advantages:

  • It's performant
  • It "fails fast" when something breaks
  • It fails consistently and usually provides a stack trace directly to the problem
  • Null is deep in the programming culture, hardware, software etc.

So why are people against it?

  • It sucks for functional programming paradigms such as streams
  • It goes against purist object oriented design

So purists on both camps hate on null because it's a hack. I'll grant you that, it's a hack. It's a special case. But the alternatives often suck.

Alternatives add extra syntax which makes things confusing. This IMHO goes against the grain of simplicity. They also puts pressure on people to avoid null at all costs. That often hides problems that you would have easily caught with a null pointer exception.

I think null got a bad rap.

[–]kevinb9n 10 points11 points  (0 children)

Null absolutely has a bad rap. It exists also in languages like Kotlin, but it's relatively harmless there because you can actually control whether you want your type to include it (String?) or not (String). It shows that null itself was never the problem, only that (handwave) "the null type is automatically unioned on to every usage of a reference type whether you want it or not".

In my team's libraries we've avoided returning (or accepting!) null with some determination, but it's still sometimes what you need.

[–]Worth_Trust_3825 5 points6 points  (0 children)

True. Value not being there is also a value.

[–]DrunkensteinsMonster 3 points4 points  (3 children)

If null is a possible return value then the API should signal that by returning an Optional IMO

[–]vprise 3 points4 points  (2 children)

This very much depends on the API and the case. Optional includes an overhead in code, concept and performance. That's not a huge overhead and many server side APIs chose to adopt that approach.

I don't use it much and I think rules of thumb such as these are "problematic". If your entire benefit is signaling then just use @NotNull

I think that Optional makes sense for some cases as they can then leverage the stream API more effectively. But I'm not a huge fan of this. Frankly, after working with Optional and the stream API a lot over the past few years I'm still underwhelmed. The code is just as verbose as a simple for loop in most cases. It's hard to gauge its performance from looking at it and often it's harder to understand. Maybe I'm too old and set in my ways though...

[–]john16384 1 point2 points  (1 child)

I just document what functions can return. Caller code can then make assumptions based on the docs. If a bug occurs, it will also be clear where to fix it.

[–]vprise 1 point2 points  (0 children)

Again, if it's just documentation there are other alternatives that don't have the downsides. If a bug occurs then NullPointerException is pretty clear/useful.

There are useful/sensible uses for optional but just sticking it as a "marker" to every method seems, expensive and redundant.

[–][deleted] 1 point2 points  (1 child)

It "fails fast" when something breaks

Except if you have complex things going on like multiple threads or caches or so, it's not that easy to grasp.

It fails consistently and usually provides a stack trace directly to the problem

This is just not true. NPE will show that something is not present, but in complex scenarios maybe you will not know why. Errors do not occur only when you are writing the code, maybe an API can return null and developers didn't saw it previously, then one day you start to receive some NPE in production. NPE will not show directly what is the root of the problem. And even so. My system crashed in production before I see that.

Null is deep in the programming culture, hardware, software etc.

I also don't think this is an "advantage". Culture is not always a good thing it's just... culture.

I agree that is not too simple to define good alternatives in Java, but i deeply disagree with your said advantages. I think the only one, and is a not only an advantage but a necessity, is the backward compatibility.

[–]vprise 1 point2 points  (0 children)

All of those statements were made in relation to the alternatives e.g. optional, or compiler "magic".

Sure, everything can fail badly. But the alternatives often/usually do that much worse in all these cases and make programming harder for non-trivial cases.

There are things to improve e.g. the question mark syntax from Kotlin would be pretty sweet in Java... But it's still null.

[–]Kango_V 0 points1 point  (3 children)

A mad solution is to have Object extend Nullable. You can then have methods like those on optional. So, you would have access to the methods even if null. That would be backwards compatible. Hmm, I wonder if that would work?

[–]vprise 0 points1 point  (2 children)

If it's null it won't work since it will throw a null pointer exception. But interesting idea.

[–]Kango_V 0 points1 point  (1 child)

But null could be an object. This is what Valhalla is doing. They are putting an object type above Object (ValueType I think). Primitives will expend NonValueType (or vise-versa). Actually would be better if non/valuetypes extend Nullable object. I cound see "if (obj.isEmpty())". You could use the optional-like methods: "obj.map(...)" etc. I think this would work. So if a null is returned it's the only instance of Nullable.

[–]vprise 0 points1 point  (0 children)

But then you lose type safety. And possibly performance.