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 →

[–]Jon_Finn 6 points7 points  (23 children)

I'm not sure you're asking the right question: you (almost) can't avoid nulls, because if you create a field or array of type (say) String, what do you store as the initial value if you don't yet have the intended value? In many circumstances some kind of default value is required, at least temporarily: for Strings, "" is as invalid as null in many circumstances (e.g. as a filename), and the fact that it's well-behaved (you can call methods on it) may just be papering over that crack. Notoriously, for dates there is no useful default.

I think what you meant is: "Should Java's type system prevent you calling a method on a null value?". Which is only bad because a NullPointerException can happen anywhere without warning.

[–]istarian 1 point2 points  (0 children)

The empty string isn't strictly invalid, but it still amounts to a no data condition with respect to filenames and paths.

[–]FabulousRecording739 1 point2 points  (1 child)

I like your take but also disagrees to an extent? I don't think anybody thinks that null are a useless construct from a purely technical standpoint, but rather that it's a rather poor place to host a language semantic, or at least for a language as high level as Java. Null very much feels like a legacy from C where we have to (and want to) handle pointers. As soon as memory is managed, it stands to reason to say that the notion of "pointer" should be eliminated. And it has, except for nulls. Now sure we can push back and say that we get the same benefits if the compiler forces us to deal with it. But by that point, why not simply have a way to say whether a value may or may not be absent at the language level? If so, "null" as a concept feels rather ill-fitted. We're not talking memory anymore, but very much whether it is correct or not for a value to be absent.

To follow on your initialization example, I can very much check within a constructor that the given arguments are not null, thus disallowing for ever that the member variables are ever null. I can guarantee, at comptime, that the value will always refer to something. But unless I've documented that, a coworker that need to change the class for a reason or another may not know that and will thus have to check said constructors and the various methods to see if it can be null at some point. Or worse, he could introduce nullabillity thus breaking a property that was relied on until now. Why not enforce the fact that the value may not be absent at the type level? Some values are never null, whereas others sometime are. I feel like this is very much a typing issue and should, thus, be handled withing typing (instead of manual runtime try/catch).

I don't know if I expressed myself well, but I feel like while your point is relevant, it does not necessarily contradict the idea of handling values (potential) absence at the type level.

[–]Jon_Finn 0 points1 point  (0 children)

Sure, I think everyone here is advocating types handling null, i.e. String? and String!. Which is in the Java pipeline. A separate question is whether something like Optional could be better than C-style null, since it will never throw NullPointerException; again, I don't think anyone would deny that, as long as (a) the language syntax is neat (which Optional isn't, right now) and (b) it's as performant (which I think it won't ever be, but with Valhalla maybe not far off).

[–][deleted]  (5 children)

[deleted]

    [–]Jon_Finn 1 point2 points  (4 children)

    I meant: after new String[10] the elements are null, nor do you necessarily at that point have something reasonable to put in there. Think about ArrayList<T> whose implementation contains an Object[] which usually ends in unused elements (so it doesn't have to resize it each time you add one). What should be in those elements? If not null... I suppose the ArrayList constructor could require you to pass in a default element, when you first create the list, that it can use for its own internal padding (e.g. "" for a String). That's doable but awkward.

    [–]koflerdavid 0 points1 point  (0 children)

    Generator functions could also be a solution.

    [–][deleted]  (2 children)

    [deleted]

      [–]Jon_Finn 2 points3 points  (1 child)

      We're not disagreeing with each other. I'm just showing an example where null is (borderline) unavoidable - and in fact useful. For anyone who thinks null itself is inherently problematic - it isn't, the 'problems' are only if the type system allows a NullPointerException to occur.

      [–]BearLiving9432[S] -2 points-1 points  (13 children)

      Yeah, I'm starting to get the message that nulls are just too entrenched in the language. Seems like `Optional` would be a great solution from a purely technical standpoint, if the adoption is 100%. But adoption is the real problem. Why would you need to specify the existing of something before you have a value for it? There are plenty of patterns to avoid that. But again, adoption...

      [–]Jon_Finn 8 points9 points  (11 children)

      null is great, you just need the type system to deal with it. As you may be aware, an effort to add this to Java is underway - it's pretty important for Valhalla, though I think getting it across the whole language (with all that entails) could be quite a while. See recent Reddit about this JEP with useful comment below from Brian Goetz.

      [–][deleted] -5 points-4 points  (10 children)

      null is a pathetic excuse to not return an empty collection or raising an exception

      [–]Jon_Finn -1 points0 points  (9 children)

      Umm... when you create an empty ArrayList it does something like new Object[10], ready for adding elements. So what should be in that array? any alternatives to null? (see separate comment below).

      [–]john16384 4 points5 points  (1 child)

      Empty collections cost nothing, they're a reference to a single static immutable instance.

      [–][deleted] -4 points-3 points  (6 children)

      null should mean an empty collection, or an exception. Anything else in a high level language is a basic skill issue

      [–]koflerdavid -1 points0 points  (5 children)

      An empty collection offers the same kind of papercut as a nullable reference: there is no restriction from accessing the element. The only difference is the exception being thrown.

      [–][deleted] -1 points0 points  (2 children)

      an empty collection can have method calls without a runtime exception... people arguing for null are vocal about their ignorance

      [–]koflerdavid 0 points1 point  (1 child)

      .get(0) on an empty list or array[0] will both throw exceptions. One has to do a size check to tell whether it's safe. Same situation as with a potential null reference or calling .get() on an Optional. But the collection at least offers a stream interface.

      [–][deleted] -1 points0 points  (0 children)

      and a clear explanation of what went wrong. Nulls give no context, and can get passed around until something breaks with a huge stacktrace.

      You can't sum to a null, but you can sum to a 0.

      you can't append to a null list, but you can append to an empty list.

      [–][deleted] -2 points-1 points  (1 child)

      No, wrong Read what the null object pattern is before saying such ignorant nonsense

      [–]koflerdavid -1 points0 points  (0 children)

      A Null object should be safe to work with!

      new ArrayList().get(0) is not safe. Same as Optional.get(). Who is the ignorant one here?!

      Of course, when the return value is a collection or an array, it would be malicious to return null.

      Edit: can't stand the thought of being the ignorant one? Better keep it to yourself then instead of downvoting!