Использование ссылок на методы в экземпляре, который будет определен во время выполнения в Java
Я проверял правила использования ссылок на методы, но написанный мной код не компилировался. Компилятор постоянно говорит мне, что я не могу ссылаться на нестатический метод из статического контекста. Однако в Java-документах прямо написано, что можно использовать "::" для "ссылки на метод экземпляра произвольного объекта определенного типа". Кто-нибудь может указать, что не так с моим кодом? Спасибо!
package Test;
import java.util.function.BiPredicate;
class Evaluation {
public boolean evaluate(int a, int b) {
if (a-b ==5){
return true ;
}
return false;
}
public void methodTest() {
BiPredicate<Integer, Integer> biPredicate = Evaluation::evaluate;
System.out.println(biPredicate.test(6,1));
}
}
Изменить: После прочтения ответов мне было интересно, если это так, что ссылка на метод экземпляра по имени класса работает только в некоторых функциональных интерфейсах, но не в других? Например,
BiPredicate <String, Integer> biPredicate = String::startsWith;
не компилируется, пока:
Predicate <String> predicate = String::isEmpty;
компилирует. Если это так, есть ли страница / учебное пособие / что-нибудь, на что кто-нибудь может отослать меня, чтобы объяснить, какие интерфейсы функций совместимы, а какие нет?
3 ответа
Если ваш метод является методом экземпляра, то вы должны вызвать его в некотором экземпляре, например:
public void methodTest(){
BiPredicate<Integer, Integer> biPredicate = this::evaluate;
System.out.println(biPredicate.test(6,1));
}
Поскольку вы не используете какие-либо переменные экземпляра или метод, вы можете просто сделать его статическим и сохранить его как есть.
При статической ссылке на метод экземпляра возвращаемый функтор принимает дополнительный аргумент, представляющий экземпляр.
interface Func {
boolean evaluate(Evaluation instance, int a, int b);
}
...
Func biPredicate = Evaluation::evaluate;
System.out.println(biPredicate.evaluate(new Evaluation(), 6, 1));
Но вам нужно будет передать экземпляр Evaluation
при звонке
Так как ваш evaluate
Метод не использует поля экземпляра, вы можете сделать это static
то вам не нужно передавать экземпляр, и вы можете использовать только BiPredicate<Integer, Integer>
как ты пытался.
Я все еще пытаюсь выяснить правило, которое применяется, но проблема исчезнет, если вы используете
BiPredicate<Integer, Integer> biPredicate = this::evaluate;
Я ломаю голову над https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html но насколько я могу понять, потому что Evaluation::evaluate
заставляет компилятор создать произвольный объект типа Evaluation
и вы вызываете это из объекта такого типа, что правило другое. Вы должны вызывать его из определенного объекта, внутри которого methodTest
метод появляется.
Хотя у меня нет объяснения, решение состоит в том, чтобы использовать this::evaluate
, Это однозначно связывает ссылку на метод с вызывающим его объектом.
Примечание: вам не нужно оценивать boolean
в качестве условного для того, чтобы вывести boolean
от boolean
, Вы могли бы просто return a - b == 5;
,
Я, вероятно, слишком поздно отвечать на этот вопрос, но, поскольку вопрос все еще остается без ответа, я хотел бы попытаться ответить.
Я думаю, что ОП пытается достичь упущения.
Я понимаю, что OP пытается понять, почему что-то вроде этого сработает:
String str = "abc";
Predicate<String> methodRef = str::startsWith;
methodRef.test("s");
а потом,
Predicate <String> predicate = String::isEmpty
Работает и аналогично, почему бы не
Predicate <String> predicate = String::startsWith;
Компиляция, которая принимает компиляцию имени класса String.
Это просто потому, что Predicate в основном принимает любой аргумент и возвращает логическое значение. Это неправильная установка для данной проблемы.
Вместо этого вы можете попробовать,
BiFunction<String, String, Boolean> methodRef2 = String::startsWith;
methodRef2.apply("sdsdfsd", "sdfsdf");
Это будет работать, поскольку для startwith требуется исходная строка, строка для проверки и возвращаемое значение. В основном есть 4 способа вызывать ссылки на методы в Java 8
- Вызов статических методов.
- Вызов методов экземпляра.
- Вызов методов класса
- Конструкторы