Maybe I am not fully understanding the concept of Java 8 functional interfaces and/or method references. I just don't understand why the following code has "The target type of this expression must be a functional interface":
import java.time.LocalDate;
interface Today{
LocalDate getTodayDate();
}
Class to test:
class Test{
public static void main(String[] args) {
Today today = () -> LocalDate.now();
System.out.println(today::getTodayDate);//Problem with this one
}
}
How to print the values using method reference? in method references you just give the name of the function (println), they don't take arguments. You can create your own function that accepts a string and calls toUpperCase and then println, and then give the name of your function as the method reference name.
Java provides a new feature called method reference in Java 8. Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
To make the code clearer, you can turn that lambda expression into a method reference: Consumer<String> c = System. out::println; In a method reference, you place the object (or class) that contains the method before the :: operator and the name of the method after it without arguments.
Interface BiFunction<T,U,R> This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. Represents a function that accepts two arguments and produces a result. This is the two-arity specialization of Function .
You're using your method reference in a context where its target type is unknown.
It would have worked if java.io.PrintStream
had a method like the following:
public void println(Today dateSupplier){
print(dateSupplier.getTodayDate());
}
But that's not the signature of println
.
There's no reason to do this, but the way to make your code work is to invoke your own interface method, but this can't be justified...
System.out.println(today.getTodayDate()); //calls println(Object)
Unless this contract involves more than one classes/types, you may need to redesign your code.
In your question description you say that the error you get is: "The target type of this expression must be a functional interface"; but the line where you show that:
System.out.println(today::getTodayDate);//Problem with this one
would exhibit a different error message. So I guess a broader explanation is needed.
It seems you first need to create a @FunctionInterface
called Today
for this code to work, something like:
@FunctionalInterface
interface Today {
LocalDate getTodayDate();
}
When that is created, this would work too:
Today today = () -> LocalDate.now();
which would be equivalent of:
Today today = LocalDate::now;
There's not a real need to create Today
since java.util.Supplier<T>
exists and does the same thing - takes nothing as input and returns T
; but if you wanted to play around - you could.
Actually the fact that you have introduced this Today
interface will make explaining things a bit easier.
The compiler sees : today::getTodayDate
(in the System.out.println(today::getTodayDate);
line) and has to "understand" what that is; it could be at least two things : Today
or java.util.Supplier
- it can't tell for sure; that is why it is said that lambda expressions and methods references are poly expressions - their type is inferred in the context of usage (just like generics). Since the compiler can't tell what that really is, it fails.
You could make an explicit cast to the type for this to compile:
System.out.println((Today) today::getTodayDate);
or:
System.out.println((Supplier<LocalDate>) today::getTodayDate);
But the problem is that even if this compiles and works and prints "something" - what it really prints is un-specified in the JLS
and is implementation specific.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With