Справочник по методу. Невозможно сделать статическую ссылку на нестатический метод

Может кто-нибудь объяснить мне,
почему передача нестатического метода-ссылки на метод File::isHidden в порядке,
но передача метода ссылки на нестатический метод MyCass::mymethod - дает мне "Невозможно сделать статическую ссылку на нестатический метод" ?

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

Ответ 1

Ссылки методов на нестатические методы требуют, чтобы экземпляр работал.

В случае метода listFiles аргумент равен FileFilter с accept(File file). Когда вы работаете с экземпляром (аргументом), вы можете ссылаться на его методы экземпляра:

listFiles(File::isHidden)

который является сокращением для

listFiles(f -> f.isHidden())

Теперь почему вы не можете использовать test(MyCass::mymethod)? Потому что у вас просто нет экземпляра MyCass для работы.

Однако вы можете создать экземпляр, а затем передать ссылку метода на свой метод экземпляра:

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

или

test(new MyCass()::mymethod);

Ответ 2

Как отметил peter-walser, поскольку MyCass::mymethod является методом экземпляра, он требует, чтобы экземпляр был преобразован в экземпляр Function.

static перед объявлением интерфейса просто делает его статическим интерфейсом, он не превращает каждый метод в статический.

Возможным решением было бы объявить метод внутри класса статическим:

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

Чтобы лучше понять, как это работает, вы можете рассмотреть код, эквивалентный ссылочной ссылке метода MyCass::mymethod, которая (при условии вышеописанного измененного объявления MyClass):

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

Ваш исходный код попытается выполнить сортировку перевода:

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

Другая возможность заключается в использовании BiFunction вместо FunctionalInterface. В этом случае первым аргументом apply будет объект, а второй будет аргументом mymethod.

Ответ 3

Короткий ответ:

Вы пытаетесь получить доступ к статическому методу через класс.

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

Такой же как

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

Решение

Сделайте функцию статичной

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

Или используйте объект в качестве ссылки

public static void main(String[] args) {
  MyCass myCass = new MyCass();
  test(myCass::mymethod);
}