12

Can someone explain to me,
why passing a non-static method-reference to method File::isHidden is ok,
but passing method reference to a non-static method MyCass::mymethod - gives me a "Cannot make a static reference to the non-static method" ?

public static void main(String[] args) {
    File[] files = new File("C:").listFiles(File::isHidden); // OK
    test(MyCass::mymethod); // Cannot make a static reference to the non-static method
}

static interface FunctionalInterface{
    boolean function(String file);
}

class MyCass{
    boolean mymethod(String input){
        return true;
    }
}

// HELPER
public static void test(FunctionalInterface functionalInterface){}
Skip
  • 6,240
  • 11
  • 67
  • 117

3 Answers3

11

Method references to non-static methods require an instance to operate on.

In the case of the listFiles method, the argument is a FileFilter with accept(File file). As you operate on an instance (the argument), you can refer to its instance methods:

listFiles(File::isHidden)

which is shorthand for

listFiles(f -> f.isHidden())

Now why can't you use test(MyCass::mymethod)? Because you simply don't have an instance of MyCass to operate on.

You can however create an instance, and then pass a method reference to your instance method:

MyCass myCass = new MyCass(); // the instance
test(myCass::mymethod); // pass a non-static method reference

or

test(new MyCass()::mymethod);

Edit: MyCass would need to be declared static (static class MyCass) in order to be accessible from the main method.

Peter Walser
  • 15,208
  • 4
  • 51
  • 78
  • 2
    You cannot instantiate `MyClass` from within a `static` method (such as `main`) because is is a _non-static_ inner class. You would have to declare the class as static. I am assuming the code in the original example is wrapped inside a class. – Marco Torchiano Sep 17 '15 at 10:06
  • @Peter As per the documentation, Method References is absolutely not a static call. It works on both static and non- static methods. If going by your explanation then who exactly creates the instance in the case of String class private Function f1 = String::toUpperCase; – shrishti May 16 '20 at 19:05
1

As peter-walser pointed out, since MyCass::mymethod is an instance method it requires an instance to be converted to a Function instance.

The static in front of your interface declaration just makes it a static interface, it does not turn each method into a static one.

A possible solution would be to declare the method inside the class as static:

class MyCass{
   static boolean mymethod(String input){
       return true;
   }
}

To understand better how it works, you can consider the code equivalente to the method reference MyCass::mymethod that is (assuming the above modified declaration of MyClass):

new FunctionalInterface{
  boolean function(String file){
    return MyClass.mymethod(file);
  }
}

Your original code would attempt to sort-of translate into:

new FunctionalInterface{
  boolean function(String file){
    return _missing_object_.mymethod(); # mymethod is not static
  }
}

Another possibility is using a BiFunction instead of your FunctionalInterface. In that case the first argument of apply would be the object and the second would be the argument to mymethod.

Marco Torchiano
  • 712
  • 7
  • 21
  • 1
    Your first example has to be `MyClass.mymethod(file)`. The OP's code would also be translated into that. That's where the "Cannot make a static reference ..." error comes from. There is no static reference in your second example. – a better oliver Sep 17 '15 at 12:05
0

Short answer:

You're trying to access a static method through the class.

test(MyCass::mymethod); // Cannot make a static reference to the non-static method

Is the same as

test(v -> MyCass.mymethod(v)); // static access

Solution

Make the method static

class MyCass {
  static boolean mymethod(String input) {
    return true;
  }
}

Or use an object as reference

public static void main(String[] args) {
  MyCass myCass = new MyCass();
  test(myCass::mymethod);
}
AMagyar
  • 5,108
  • 3
  • 13
  • 17
  • 1
    Incase of String class, even though toUppercase is non-static then why this does not give error Function f1 = String::toUpperCase; – shrishti May 16 '20 at 19:17