RFR 9: 8138963 : java.lang.Objects new method to default to non-null

John Rose john.r.rose at oracle.com
Sat Oct 31 19:44:31 UTC 2015


On Oct 31, 2015, at 4:17 AM, Remi Forax <forax at univ-mlv.fr> wrote:
> 
> Hi John,
> I think there is a good reason to not reuse/enhance the requireNonNull prefix,
> requireNonNull here is used to check a precondition or an invariant (a contract), hence a name that starts with 'require' like in Eiffel.
> (BTW re-reading this thread, Brian already said that)

Ah, of course—that's where require came from, from contract terms.  Thanks.

> requireNonNullElseGet is not something that checks a contract and as you said, nonNull is not a good prefix too, so we should starts a new family.

It seems to me that, even so, "require*" makes excellent logical sense for the proposed use case.  As I said, it requires a slight adjustment (really, an *expansion*) of the contract viewpoint.  I think we should be happy to think of the new "require*" logic as an "extended contract" or "contract with fallback/repair".

Why shouldn't contract checks (at least in our system) offer repairs?  Why must "require", as imported from Eiffel (or some such place) dictate the meaning of a family of Java methods?  If I am working on new Java code, and I want to enforce a dynamically checked condition P on some value X, I *first* think, "X must be (is required to be) P", and then as a *secondary* thought I think, "what event E should happen if that fails?"  In this case, X is a reference value and P is "must not be null".  E can often be:

- throw NullPointerException
- throw IllegalArgumentException
- throw AssertionError (use assert syntax)
- replace X with an ad hoc fallback value
- replace X with the result of some ad hoc computation (Supplier.get)
- execute some ad hoc logic inline (control flow)

I understand that contract systems (per se) allow a single contract to be injected across a range of sites, and so the use of ad hoc local values is impossible in those use cases, but (again) we are not designing a contract system here.

— John

P.S.  If we did add a contract system, perhaps we would end up with double-requires, as:

class Box<T> {
  private T value;
  static require<in value> { Objects.requireNonNull(value); }
  // value null-checked before every storage
  ...
}

This suggests there is only a weak linkage between some hypothetical contract system and the present API.

P.P.S.
> what about:
>  <T> T coalesceNull(T, T)
>  <T> T coalesceNullGet(T, Supplier<? extends T>)

(Sorry, not for my bikeshed.)


More information about the core-libs-dev mailing list