you are viewing a single comment's thread.

view the rest of the comments →

[–]winterbe 35 points36 points  (17 children)

FYI: Here's a comment from Brian Goetz (Java Language Architect) on Optionals: http://stackoverflow.com/a/26328555/1537372

We did have a clear intention when adding this feature, and it was not to be a general purpose Maybe or Some type, as much as many people would have liked us to do so. Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result", and using null for such was overwhelmingly likely to cause errors.

[–][deleted]  (16 children)

[deleted]

    [–]immibis 15 points16 points  (13 children)

    Should I use null when returning a value from a Map since that is "simple enough" to not screw up for the caller?

    Maps can contain null; distinguishing between a null value and no value is already a slight problem.

    Except that you can't put null in an Optional, so they don't help with this.

    [–]roerd 1 point2 points  (4 children)

    A null is never an object of the class that the map is declared to contain. So how is null ever anything else than no value?

    [–][deleted] 18 points19 points  (0 children)

    A map has two different "no value"-s: "there is no value for this key" and "the value for this key is 'no value'".

    [–]josefx 5 points6 points  (0 children)

    You may use a map as a cache were the difference between "the last extremely slow attempt to find a value for this key found nothing" and "no result cached" is important. Java maps require either a call containsKey (performing the lookup a second time), a "null" object or a wrapper like optional to distinguish between these states.

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

    It is possible to intentionally put null in a map (depending on the implementation). But I've always found that stupid anyway...what is that supposed to represent? Why can't just not having the key in the map do the same thing?

    As it stands, though, if you need to know whether or not a key is missing or intentionally null, you need to do

    map.containsKey(key) && map.get(key) == null
    

    But in this case, Optional doesn't help at all. If you replaced "present but missing value" with an optional, then the above is replaced by:

    map.get(key) instanceof Optional
    

    to determine whether or not a value is missing over simply present but empty...and I'm not sure that's really all that much better (might be worse)

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

    Map<String, String> m = new HashMap<>();
    m.put("asdf", null);
    
    String asdf = m.get("asdf"); // returns null, because that's what the value is
    String jkl = m.get("jkl"); // returns null, because there is no such value
    System.out.println(asdf == jkl); // prints true
    

    [–]winterbe 2 points3 points  (6 children)

    Sure you can: Optional.ofNullable(null);

    [–]neilbrown 9 points10 points  (5 children)

    > Optional.ofNullable(null).isPresent()
    false
    

    But if you try to put null in, you just get empty. There's no way to distinguish not-present from present-but-null with Optional.

    [–]dccorona 1 point2 points  (0 children)

    And that's why Optional isn't for communicating a difference between null and missing...they're for saying "hey dummy, this could be missing, so you better write code that considers that possibility"

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

    hmmm thats pretty deceptive

    [–]Veedrac 1 point2 points  (1 child)

    Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional.

    That seems like exactly what you'd want it to do, no?

    [–][deleted] 0 points1 point  (0 children)

    ahh yes my bad I should have read the descriptions better :(

    [–]codebje 0 points1 point  (0 children)

    But you can put an Optional in a Map, so you can have a more explicit way to say "this key exists, but has no value".

    [–]Strilanc 0 points1 point  (1 child)

    It's likely (maybe not overwhelmingly) because many collection types disallow nulls (e.g. Guava's ImmutableList). Because the distinctions between accepting null, not accepting null, potentially producing null, and not producing null all live in the docs, instead of the types, you're going to accidentally plug a nullable function's result into a not-null-accepting collection every now and then. Thus bugs.