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

Может кто-нибудь объяснить мне,
зачем передавать нестатический метод-ссылку на метод 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){}

2 ответа

Решение

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

В случае с 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);

Как отметил Питер-Уолсер, так как 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,

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

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

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);
}
Другие вопросы по тегам