Можно ли использовать ссылку на метод со статическим методом интерфейса? - PullRequest
0 голосов
/ 10 октября 2018

Это мой первый код:

public class MethodReference {
    public static void main (String []args) {
        Stream<String> s = Stream.of("brown bear", "grizzly");
        s.sorted(Comparator.reverseOrder()).forEach(System.out::print);
        //...
    }
}

Результат: grizzlybrown bear

Это мой второй код:

public class MethodReference {
    public static void main (String []args) {
        Stream<String> s = Stream.of("brown bear", "grizzly");
        s.sorted(Comparator::reverseOrder()).forEach(System.out::print);
        //...
    }
}

Результат: ошибка компилятора

Мои вопросы: почему во втором коде есть ошибка компилятора?Не могу ли я использовать ссылку на метод для статического метода функционального интерфейса?

Я знаю, что не могу использовать ссылку на метод с методом по умолчанию для функционального интерфейса.Я знаю, что могу использовать ссылку на метод с классом в 5 случаях:

Класс

  • Класс :: staticMethod

  • Класс:: instanceMethod

  • instance :: instanceMethod

  • Класс :: new

Функциональный интерфейс

  • Интерфейс :: abstractMethod

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Comparator.reverseOrder() - это выражение, которое разрешается в тип Comparator, потому что это то, что оно возвращает.

Comparator::reverseOrder - это выражение, которое разрешается в метод , который не принимаетаргументы и возвращает Comparator например, Supplier<Comparator<String>>, хотя это может быть любой соответствующий функциональный интерфейс.

Во втором случае вы пытаетесь передать метод (который предоставляет Comparator) в качестве аргумента,Метод не хочет этого - он просто хочет сам Comparator.

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

s.sorted(new Comparator())

vs

s.sorted(new Supplier(new Comparator()))

Чтобы ответить на ваш второй вопрос о том, возможно ли когда-либо использовать ссылку на метод для статического метода интерфейса - да, абсолютно!

Если мы объявимследующий метод:

<T> void giveMeAComparatorSupplier(Supplier<Comparator<T>> supplier) { }

тогда мы определенно можем вызвать его со ссылкой на метод

giveMeAComparatorSupplier(Comparator::reverseOrder);

(И, к вашему сведению, ваш синтаксис ссылки на метод неверен - он никогда не использует ())

0 голосов
/ 10 октября 2018

Две вещи не так с вашим вторым кодом.Во-первых, ссылки на методы не используют скобки или аргументы вообще.Вам нужно будет предоставить только метод, который будет вызван позже;Вы не вызываете метод в этот момент.

Во-вторых, метод sorted требует Comparator, а не функциональный интерфейс, который бы поставлял Comparator.Для метода требуется Comparator, уже созданный и готовый к работе, а не функциональный интерфейс, который будет предоставлять Comparator при необходимости.

Он не имеет ничего общего с тем фактом, что Comparator является интерфейсом;обычно можно создать ссылку на метод интерфейса static.Это связано с тем, что sorted нужен фактический экземпляр Comparator, а не экземпляр функционального интерфейса, когда вы можете предоставить ссылку на метод.

Так что даже если вы отключитескобки, это все еще не скомпилируется.Только ваш первый код, который напрямую передает Comparator, будет скомпилирован и работать как положено.

...