In Java 8 is it possible to call 2 reference methods in a row?
customer::new::getName
Can be concatenated 2 methods reference of the form:
a::b::c
3 Answers 3
How to inline two method reference expression ?
Let's decomposing Customer::new::getName expression;
T1 customer = Customer::new;
T2 name = customer::getName;
according JLS described Method Reference Expression,so T1 and T2 must are FunctionalInterface.
A method reference expression is compatible in an assignment context, invocation context, or casting context with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.
when you use Supplier<Customer> with T1 then the compiler reports error:can't resolve method getName defined on Supplier. but you can define your own FunctionalInterface, e.g: CustomerSupplier.
interface CustomerSupplier {
Customer get();
default String getName() {
return get().getName();
}
}
then you can refer Customer::new to CustomerSupplier:
CustomerSupplier customer = Customer::new;
Supplier<String> name = customer::getName;
Indeed, you can inline two expression together in further, but each method reference expression must be a FunctionalInterface, so you must cast Customer::new to CustomerSupplier.
Supplier<String> customerName = ((CustomerSupplier) Customer::new)::getName;
However, the simplest one is access directly that provided by @Holger.
Supplier<String> customerName = () -> new Customer().getName();
How to chain two method reference expression ?
Due to Supplier has no methods for composing FunctionInterface, but you can chain the method reference expression like this:
interface Reference<T> extends Supplier<T> {
static <T> Reference<T> of(Supplier<T> reference) {
return reference::get;
}
default <R> Reference<R> of(Function<T, R> after) {
return () -> after.apply(get());
}
}
//NOTE:Reference is derived from Supplier, so it is compatible with Supplier.
Supplier<String> customerName = Reference.of(Customer::new).of(Customer::getName);
However, you can introduce a method to avoid introduce a type for composing Function Interfaces that provided by @Holger.
private <T, R> Supplier<R> map(Supplier<T> target, Function<T, R> mapper) {
return () -> mapper.apply(target.get());
}
Supplier<String> customerName = map(Customer::new, Customer::getName);
Comments
In Java 8 is it possible to call 2 reference methods in a row?
No, it's not possible to chain methods when using method references because a method reference is essentially a shorthand syntax for a lambda expression that executes just ONE method. Hence, once you start chaining methods it would no longer be valid syntax for a method reference.
syntax
Object::methodName
Comments
No, you can't chain two method references.
Basically, a method reference is a syntactic sugar which will allow you to pass the definition of an existing method to a Lambda expression (which implements single abstract method).
()->new customer().getName()or()->a.b().c()?