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.ri...@oracle.com>
À: "core-libs-dev" <core-libs-dev@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
-