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){}
3 Answers 3
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.
2 Comments
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.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.
1 Comment
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.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);
}