Как реализовать ссылку на метод в качестве предиката? - PullRequest
3 голосов
/ 11 октября 2019

Я новичок в java8, и я пытался понять этот кусок кода. Это фрагмент кода:

Stream.of("A", "B", "C").anyMatch(someObj.getStringValue()::equalsIgnoreCase)

someObj.getStringValue() ссылается на некоторый объект, а getStringValue() возвращает некоторое строковое значение.

Каков эквивалентный предикат ссылки на метод, передаваемый вanyMatch(...)?

Насколько я понимаю, это было бы эквивалентно:

Predicate<String> p = new Predicate<String>() {
    @Override
    public boolean test(String t) {
        return someObject.getStringValue().equalsIgnoreCase(t);
    }
}
Stream.of("A", "B", "C").anyMatch(p)

При этом я получаю сообщение об ошибке "Локальная переменная someObject, определенная во внешней области видимости, должна быть окончательной или эффективнойокончательный «. Любое объяснение этого приветствуется.

1 Ответ

3 голосов
/ 11 октября 2019

Выражение someObj.getStringValue() вычисляется снаружи, поэтому эквивалентный код будет:

final String x = someObject.getStringValue();
Predicate<String> p = new Predicate<String>() {
    @Override
    public boolean test(String t) {
        return x.equalsIgnoreCase(t);
    }
}
Stream.of("A", "B", "C").anyMatch(p)

, где локальная переменная x тоже "анонимна".

Из-за этогоsomeObject не обязательно должен быть эффективно окончательным .

Вы можете проверить это поведение для лямбда-выражения в отладчике, поместив точку останова внутри getStringValue(),Несмотря на то, что метод test() вызывается 3 раза (поскольку поток содержит 3 элемента и при условии отсутствия совпадения), метод getStringValue() будет вызываться только один раз.

...