50

Summary pretty much says it all. Here's the relevant snippet of code in ImmutableList.createFromIterable():

  if (element == null) {
    throw new NullPointerException("at index " + index);
  }

I've run into this several times and can't see why a general-purpose library function should impose this limitation.

Edit 1: by "general-purpose", I'd be happy with 95% of cases. But I don't think I've written 100 calls to ImmutableList.of() yet, and have been bitten by this more than once. Maybe I'm an outlier, though. :)

Edit 2: I guess my big complaint is that this creates a "hiccup" when interacting with standard java.util collections. As you pointed out in your talk, problems with nulls in collections can show up far away from where those nulls were inserted. But if I have a long chain of code that puts nulls in a standard collection at one end and handles them properly at the other, then I'm unable to substitute a google collections class at any point along the way, because it'll immediately throw a NullPointerException.

Matt McHenry
  • 20,009
  • 8
  • 65
  • 64
  • 1
    Question: do you interpret "general-purpose" to mean "100% of purposes" or "95% of purposes"? – Kevin Bourrillion Feb 12 '10 at 17:12
  • 1
    Re: edit 2: This is to claim that all those intermediate points along the way should be agnostic about whether they're passing nulls through or not. I don't agree with this! Every one of these APIs should either explicitly allow null or explicitly disallow it. Everyone can continue to press this point all you want, but please realize it's pure complaining, and not constructive at all. Even if you convinced every one of us we were wrong, wrong, wrong (unlikely, of course), it still wouldn't matter: it's not like we can change it anymore anyway. – Kevin Bourrillion Feb 13 '10 at 18:58
  • 1
    relevant: http://code.google.com/p/guava-libraries/wiki/LivingWithNullHostileCollections – Kevin Bourrillion Sep 21 '11 at 01:38
  • "general-purpose" means "useful for 100% of purposes". Otherwise it's not a general solution, it's just a 95%-general solution. Even if Google "personally" don't like nulls (I don't really like them either, admittedly) sometimes you have to store an array of names where some things don't have names, and using an Optional wrapper wastes storage space (the point of ImmutableList is to be efficient. Allegedly.) – Hakanai May 28 '13 at 23:43
  • Link provided by @KevinBourrillion expired. I think nowadays more or less similar is a [Using and avoiding null](https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained) – Dmitrii Bulashevich Mar 12 '18 at 08:44

4 Answers4

38

I explained this at the 25-minute point of this video: https://youtu.be/ZeO_J2OcHYM?t=1495

Sorry for the lazy answer, but this is after all only a "why" question (arguably not appropriate to StackOverflow?).

EDIT: Here's another point I'm not sure I made clear in the video: the total (across all of the world's Java code), amount of extra code that has to be written for those null-friendly cases to use the old standbys Collections.unmodifiableList(Arrays.asList(...)) etc. is overwhelmed by the total (across all of the world's Java code) amount of extra checkArgument(!foos.contains(null)) calls everyone would need to add if our collections didn't take care of that for you. Most, by FAR, usages of a collection do not expect any nulls to be present, and really should fail fast if any are.

David
  • 4,744
  • 5
  • 33
  • 64
Kevin Bourrillion
  • 40,336
  • 12
  • 74
  • 87
  • I guess my track record of questions about google collections on SO isn't so hot. :-/ – Matt McHenry Feb 13 '10 at 01:25
  • 26
    -1. Don't tell me what I should or should not be putting in my collections. Nulls are often valid in my lists. It's rare that I want nulls in a set or map, but there are plenty of other tools I can use if I want to guard against null elements. – finnw Feb 13 '10 at 11:58
  • 36
    First, who's telling you not to put null in a collection? If you need to, as we Googlers need to about 5% of the time (we studied this carefully), just use a collection that supports it. Second, a choice was made, and this question asks why the choice was made. Does it really make sense to downvote the answer because you don't like the choice? It's still the answer to the question asked. – Kevin Bourrillion Feb 13 '10 at 18:51
  • 1
    Collections.unmodifiableList() isn't *really* immutable because you never know if someone is holding onto a copy of the backing list. So I find it to be an unacceptable workaround. So what we would end up doing to work around this limitation is to write a BetterImmutableList class which works exactly the same way but permits nulls. I can always use `BetterImmutableList<@NotNull String>` if I want to assert that it doesn't contain nulls anyway. But it's tragic, you know, because Guava is just so good in so many other ways. – Hakanai Nov 18 '14 at 00:31
  • 1
    Your concern about unmodifiableList doesn't apply to my example. And are you going to also rewrite EnumMap, ConcurrentHashMap, all the JDK Queues, etc. etc. for this reason? – Kevin Bourrillion Feb 05 '15 at 01:12
  • It would be helpful if the builder had a method putIfNotNull though. It would mean I could actually use the builder as a builder without having to have an if block for those cases where the values might be null. – yarrichar Nov 11 '17 at 01:23
  • 3
    I suspect if it needs to *watch a video* to explain, that must be some nonsense. – Mikhail Batcer Nov 16 '17 at 11:56
  • 1
    While a "Why" question might not be fit for StackOverflow, a "go watch this youtube" is definitely not a fit answer either and should not be the accepted answer. Yes, 95% of the time you don't want nulls in your immutable list, and yes, null sucks - we get it. The bottomline question (unless you're writing academic code) is: - if you put a null in your immutable array, do you want to blow up your 50 billion dollar space shuttle early, or do you want to risk that ... maybe it'll be fine. I was hoping for a technical answer to this question rather than an ideological one. – GaspardP Apr 22 '21 at 17:45
  • You should upvote the answer that you feel is better. But I think I know why a crappy answer got accepted. It's because when the question is "why did person X do thing Y?" that makes it kind of hard for anyone to answer that question except for person X, doesn't it? All they could do is point to what person X had said, so I decided (in some haste, I'll allow) I might as well do that myself. – Kevin Bourrillion Apr 23 '21 at 22:37
  • But it wasn't an ideological decision. It was a decision of convenience. We were tired of null-checking our collections all the time. We wanted three useful guarantees out of these collections – immutability, deterministic iteration, and null-rejection – even though we weren't about to cram all three into the class names. Our mindset was: when this isn't what you want, then you just use something else. I've never regretted this decision. – Kevin Bourrillion Apr 23 '21 at 22:43
  • Was surprised that `immutableList.contains(null)` threw an NPE, though. Would've expected a `false`. – SQB Nov 26 '21 at 12:11
  • It does return `false` - throwing would be a bug and I don't think it has ever had that particular bug. – Kevin Bourrillion Feb 04 '22 at 06:29
  • @KevinBourrillion "who's telling you not to put null in a collection" -- pretty sure that's Java telling us that we can't add nulls to unmodifiable collections. – Josh M. Mar 06 '22 at 01:35
13

In general in Google Collections the developers are of the group that does not believe that nulls should be an expected general purpose parameter.

Yishai
  • 90,445
  • 31
  • 189
  • 263
1

From Guava's Github Page

Careless use of null can cause a staggering variety of bugs. Studying the Google code base, we found that something like 95% of collections weren't supposed to have any null values in them, and having those fail fast rather than silently accept null would have been helpful to developers.

The Guava position is largely, that there are other ways to avoid nulls in collections. For example, fetching a batch of items with a specific key. E.g.

// If a widget for the given id does not exist, return `null` in the list
private List<Widget> getWidgets(List<String> widgetIds);

// Could be restructured to use a Map type like this and avoids nulls completely.

// If a widget for the given id does not exist, no entry in list
private Map<String, Widget> getWidgets(List<String> widgetIds);
Jason
  • 121
  • 1
  • 5
-3

One reason is that it allows functions that work on the list not to have to check every element for Null, significantly improving performance.

0xfe
  • 4,541
  • 1
  • 18
  • 14
  • 6
    No, the performance improvements we got from this were VERY small in the grand scheme of things. – Kevin Bourrillion Feb 12 '10 at 17:10
  • Except Function does annotate its parameter as @Nullable, so you will actually have to check that for null to satisfy code inspection, despite the fact that the list can't contain nulls. (lol) – Hakanai Jun 11 '13 at 04:35