-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Allow a @Nullable
value for the second parameter of requireNonNullElse
.
#11
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused by the example in the PR description, because it uses firstNonNull
and not requireNonNullElse
.
The method and the parameter javadoc for requireNonNullElse
both explicitly say that the second parameter has to be non-null, so I'm not sure allowing null here makes sense.
Can you elaborate?
…Else`. The existing approach follows the Checker Framework philosophy, under which passing `null` for a `@Nullable` parameter should never lead to a `NullPointerException`. (Compare `Method.invoke`, whose "receiver" _and_ "arguments" parameters are declared as non-nullable by the Checker Framework, even though some callers _can_ pass `null` for the "receiver" and some _must_ pass `null` for some of the arguments.) The JSpecify thinking has moved in the direction of saying that, if `null` should ever be permitted for a parameter, then the parameter should be declared with a type that includes `null`. And we know that many callers pass `null` for the second parameter. Here's an imaginary such caller: ```java for (Key key : union(map1.keySet(), map2.keySet()) { Value value = requireNonNullElse(map1.get(key), map2.get(key)); } ``` (We could consider making a similar change to `requireNonNullElseGet`. But it's rarely used, and perhaps no one wants to pass a `Supplier` that may return `null`, anyway. So I'm happy to leave it alone for now or to change it if that's more palatable.)
Sorry about the PR description: I had reused it from google/guava@4aaebca without editing it enough. I've updated it to use And wow, that doc is not especially clear. I had been focused on the following part, which makes it sounds like a null second argument is fine (at least in situations like the one in my PR description): jdk/src/java.base/share/classes/java/util/Objects.java Lines 318 to 319 in 234d208
There's some further text to that effect, too: jdk/src/java.base/share/classes/java/util/Objects.java Lines 316 to 317 in 234d208
But now I see what you're looking at: jdk/src/java.base/share/classes/java/util/Objects.java Lines 313 to 314 in 234d208
And arguably also this, but less so:
I think part of the question is how much the
Or:
I'm annotating the method to match the former; you're advocating for the latter. I have no real argument here, just "Obviously :) they meant to permit null": Doing so is useful in examples like mine, and rejecting null entirely would have been so easy. But the doc does everything it can to muddy the waters—really, everything it can to suggest that I'm wrong without being 100% clear about it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your updated example and explanation! This makes much more sense now.
If we just focus on values in legal executions, there are calls like requireNonNullElse(nonNull, null)
, where the second argument is null and nothing bad happens. So by our definition, I would agree we should make the parameter @Nullable
.
If I were to rewrite your example to make it more "obvious", I would end-up inlining the body of requireNonNullElse
. So again, it would make sense to allow abstracting out that logic into a helper method.
With a more conservative POV, I would continue to argue that only non-null values make sense for the second argument, to help avoid all NPEs at compile time. But then I would also want the first parameter of requireNonNull
to be @NonNull
, which we have discussed more than enough.
I think this is another example where we want additional preconditions on the method, to precisely express that either of the arguments (or both) needs to be non-null. The current @RequiresNonNull
annotation is not strong enough to express such a contract.
So overall, I agree with making this change.
The existing approach follows the Checker Framework philosophy, under
which passing
null
for a@Nullable
parameter should never lead to aNullPointerException
. (CompareMethod.invoke
, whose "receiver" and"arguments" parameters are declared as non-nullable by the Checker
Framework, even though some callers can pass
null
for the "receiver"and some must pass
null
for some of the arguments.)The JSpecify thinking has moved in the direction of saying that, if
null
should ever be permitted for a parameter, then the parametershould be declared with a type that includes
null
. And we know thatmany callers pass
null
for the second parameter. Here's an imaginarysuch caller:
(We could consider making a similar change to
requireNonNullElseGet
.But it's rarely used, and perhaps no one wants to pass a
Supplier
thatmay return
null
, anyway. So I'm happy to leave it alone for now or tochange it if that's more palatable.)