问题
As per the Documentation, Method Reference is absolutely not a static call. It works on both static and non- static methods. When we define our own non-static method in a given class and try to use it using Method Reference then the compile-time-error "cannot make static reference to non static method" is NOT seen in case of Function but only seen in case of Supplier, Consumer and Predicate. Why is that so?
class Demo{
private Function<Student, Integer> p= Student::getGradeLevel; // fine
private Supplier<Integer> s = Student::supply; // compile-time error
private Predicate<Integer> p1= Student::check; //compile-time error
private Consumer<Integer> c= Student::consume; / compile-time error
private Function<String, String> f1 = String::toUpperCase; //fine
}
class Student{
public int getGradeLevel() {
return gradeLevel;
}
public boolean check(int i) {
return true;
}
public int supply() {
return 1;
}
public void consume(int i) {
System.out.println(i);
}
}
回答1:
You have to follow both the return type and the formal parameter type of the Student
method and use the appropriate functional interface.
private Supplier<Integer> s = Student::supply; // compile-time error
The Supplier<T>
consumes nothing and returns T
. An example would be:
Student student = new Student();
Supplier<Integer> s = () -> student.supply();
The relevant functional interface for the method reference Student::supply
is
Function<T, R>
. The both following are equal:
Function<Student, Integer> function = student -> student.supply();
Function<Student, Integer> function = Student::supply;
// You have already used a method reference with the very same return and parameter types
Function<Student, Integer> p = Student::getGradeLevel;
private Predicate<Integer> p1= Student::check; //compile-time error
The very same issue but Predicate<T>
consumes T
and returns Boolean
.
Student student = new Student();
Predicate<Integer> p = i -> student.check(i);
You can use BiPredicate<T, R>
that results in Boolean
if you want to use Student::check
method reference:
BiPredicate<Student, Integer> biPredicate = (student, integer) -> student.check(integer);
BiPredicate<Student, Integer> biPredicate = Student::check;
private Consumer<Integer> c= Student::consume; / compile-time error
Again nothing new, Consumer<T>
consumes T
and returns nothing (the return type is void
).
Student student = new Student();
Consumer<Integer> c = integer -> student.consume(integer);
The method reference Student::consume
is suitable for BiConsumer
consuming both Student
and some Integer
:
BiConsumer<Student, Integer> biConsumer = (student, integer) -> student.consume(integer);
BiConsumer<Student, Integer> biConsumer = Student::consume;
来源:https://stackoverflow.com/questions/61842848/understand-the-compile-time-error-with-method-reference