shrishti
shrishti

Reputation: 95

Understand the compile time error with Method Reference

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);
    }
}

Upvotes: 2

Views: 820

Answers (1)

Nikolas
Nikolas

Reputation: 44368

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;

Upvotes: 2

Related Questions