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

Stuart Marks stuart.marks at oracle.com
Thu Oct 8 18:39:04 UTC 2015


On 10/8/15 7:44 AM, Roger Riggs wrote:
> On 10/8/2015 4:49 AM, Remi Forax wrote:
>> Hi Roger,
>> using overloads here seems to be a bad idea,
>> as a nice puzzler, what does the compiler do for these two lines of code
>>    Supplier<String> supplier = Objects.nonNullOf(null, () -> null);
>>    Supplier<String> supplier2 = Objects.nonNullOf(null, () -> "");
> The first form compiled and threw the expected NPE at runtime.
>
> In the second case, the () -> "" is a supplier<String> not a
> Supplier<Supplier<String>>.
> The compiler correctly produced a error.
>
> I don't think the method name will help the developer much and just makes the
> name longer
> for everyone else who is not producing a Supplier<Supplier<T>>.

I think there is an overloading issue here. It occurs when dealing with 
Supplier<T>, not Supplier<Supplier<T>> (which I agree would be pretty obscure).

Suppose we're trying to initialize a variable whose type is Supplier<String>. We 
might try

     static void setSupplier(Supplier<String> arg) {
         Supplier<String> supplier = Objects.nonNullOf(arg, () -> ""); // ERROR
     }

This seems like it ought to work, but it gives an error:

/Users/smarks/NetBeansProjects/Java9scratch/src/ObjectsNonNull.java:35: error: 
incompatible types: inference variable T has incompatible bounds
         Supplier<String> supplier = Objects.nonNullOf(arg, () -> ""); // ERROR
     upper bounds: Supplier<String>,Object
     lower bounds: String,Supplier<String>
   where T is a type-variable:
     T extends Object declared in method <T>nonNullOf(T,Supplier<T>)

This is with a recent jdk9/dev build, but it also seems to happen in 8u25.

You'd think the compiler would infer T to be Supplier<String> based on the 
target type, and matching of both args, but ... it doesn't.

The workaround is to supply a type witness:

     Supplier<String> supplier = Objects.<Supplier<String>>nonNullOf(arg, () -> "");

I don't know whether this is a compiler bug or just a limitation in the way type 
inference interacts with overload resolution. In any case, I'd like to be able 
to write my example code without compiler errors or having to provide a type 
witness.

If it's just a compiler bug that's likely to be fixed in 9, I'd be ok with 
proceeding with this the overload approach. Otherwise, I'd prefer to rename the 
Supplier-based method in order to avoid the issue.

s'marks

>
>>
>> The other issue is that defaultSupplier should allow covariant Supplier,
>> the signature should be:
>>    <T> T nonNullOfGet(T obj, Supplier<? extends T> defaultSupplier)
> Right, as Chris pointed out also.
>
> Thanks, Roger
>
>>
>> otherwise apart form the remark of Stephen, the code is Ok.
>>
>> cheers,
>> Rémi
>>
>> ----- Mail original -----
>>> De: "Roger Riggs" <Roger.Riggs at Oracle.com>
>>> À: "core-libs-dev" <core-libs-dev at openjdk.java.net>
>>> Envoyé: Jeudi 8 Octobre 2015 00:24:26
>>> Objet: Re: RFR 9: 8138963 : java.lang.Objects new method to default to
>>> non-null
>>>
>>> Hi,
>>>
>>> The original intent was to simplify the filling in of default values
>>> (even if null).
>>> I took Remi's point about  the canonical coalescing operator not always
>>> returning non-null
>>> but the push seems to be in the direction of making sure the result is
>>> always non-null.
>>> I'd rather add a few very useful methods and avoid those with
>>> diminishing returns.
>>>
>>> I note that nulls are discovered eventually, but doing more aggressive
>>> checking is preferred.
>>> I expect the compiler is able to squeeze out all the extra checks.
>>>
>>> In the current context of Objects that the jdk, I read the naming
>>> pattern of firstNonNull to imply
>>> access to some sequential data structure like an array or list; but it
>>> doesn't gel with me to apply it to the arg list
>>> (unless it was varargs).  The pattern of naming us "of"  as being
>>> factory producing an object
>>> from the arguments seems apropos and is concise.
>>>
>>> Please consider and comment:
>>>
>>>       <T> T nonNullOf(T obj, T defaultObj);
>>>       <T> T nonNullOf(T, obj, Supplier<T> defaultSupplier);
>>>
>>> Details are in the updated webrev:
>>>        http://cr.openjdk.java.net/~rriggs/webrev-object-non-null/
>>>
>>> Regards, Roger
>>>
>>>
>>> On 10/6/2015 6:42 PM, Remi Forax wrote:
>>>> Null coalescing is a popular operator in several languages [1] and the
>>>> usual semantics is nullOrElse and not firstNonNull.
>>>> In languages like Kotlin or Swift, because there is a distinction between
>>>> Object and Object?, it's not a big deal, you can not de-reference null by
>>>> error, anyway.
>>>>
>>>> Also note that nullOrElseGet, the one that takes a supplier also exists in
>>>> Groovy and Kotlin under the name null safe navigation.
>>>>
>>>> So even if i prefer the semantics of firstNonNull, i think we should also
>>>> include both nullOrElse and nullOrElseGet.
>>>>
>>>> regards,
>>>> Rémi
>>>>
>>>> [1] https://en.wikipedia.org/wiki/Null_coalescing_operator
>>>>
>>>> -
>>>
>



More information about the core-libs-dev mailing list