Intereting Posts
Установка проекта Android Kotlin не выполняется с помощью INSTALL_FAILED_DEXOPT Классы хранения на языке программирования Kotlin Как получить пользовательские опции в плагине protoc для java? Как переустановить уже запущенную службу поддержки музыкальных плееров Kotlin: видимый делегат свойства nullable Как запомнить состояние с помощью операторов повтора в RxJava2 Круговая зависимость при компиляции с Kotlin 1.1.2-4, но не на 1.1.2-3 Полиморфизм на функциях расширения в Котлине Поток Akka, выше по потоку, не производя значения Fade excludeTarget не работает внутри DrawerLayout Момент не может быть сериализован в соответствующий формат даже с помощью jackson-datatype-jsr310 Когда именно ключевое слово оператора требуется в Котлине? Apache FOP 2.2 Включить шрифты, используя относительный путь Приложение Spring Boot: наблюдатель файловой системы для многих путей Родственные классы супер / дочерние классы Котлина

Точное определение «функционального интерфейса» в Java 8

Недавно я начал изучать Java 8, и я не могу полностью понять концепцию «функционального интерфейса», которая необходима для реализации ямбда-выражений Java. В Java есть довольно подробное руководство по лямбда-функциям, но я застрял в главе, которая дает определение концепции функциональных интерфейсов . Определение гласит:

Точнее, функциональный интерфейс определяется как любой интерфейс, который имеет ровно один абстрактный метод.

Затем он переходит к примерам, одним из которых является интерфейс Comparator :

 public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); } 

Я смог проверить, что вместо аргумента Comparator я могу использовать функцию лямбда, и она работает (например, Collections.sort(list, (a, b) -> ab) ).

Но в интерфейсе Comparator методы compare и equals являются абстрактными, что означает, что он имеет два абстрактных метода . Итак, как это может работать, если для определения требуется, чтобы интерфейс имел ровно один абстрактный метод ? Что мне здесь не хватает?

С той же страницы, на которую вы ссылались :

Компаратор интерфейса является функциональным, потому что, хотя он объявляет два абстрактных метода, один из этих равенств – имеет подпись, соответствующую общедоступному методу в объекте. Интерфейсы всегда объявляют абстрактные методы, соответствующие общедоступным методам Object, но они обычно делают это неявно. Неявно или явно объявленные, такие методы исключаются из счета.

Я не могу сказать это лучше.

Изменить: обновлено до последнего текста этой страницы, за комментарий Мориса (спасибо!)

Q. Но в интерфейсе Comparator методы compare () и equals () являются абстрактными, что означает, что он имеет два абстрактных метода. Итак, как это может работать, если для определения требуется, чтобы интерфейс имел ровно один абстрактный метод? Что мне здесь не хватает?

A.

Функциональный интерфейс может указывать любой общедоступный метод, определенный Object, например equals (), не влияя на его статус «функциональный интерфейс». Общедоступные методы Object считаются неявными членами функционального интерфейса, поскольку они автоматически реализуются экземпляром функционального интерфейса.

Другое объяснение приведено на странице @FunctionalInterface :

Концептуально функциональный интерфейс имеет ровно один абстрактный метод. Поскольку методы по умолчанию имеют реализацию, они не абстрактны. Если интерфейс объявляет абстрактный метод, переопределяющий один из общедоступных методов java.lang.Object , это также не учитывает счет абстрактного метода интерфейса, поскольку любая реализация интерфейса будет иметь реализацию из java.lang.Object или в другом месте.

Вы можете проверить, какой интерфейс является правильным функциональным интерфейсом, используя @FunctionalInterface .

Например:

  • это работает

     @FunctionalInterface public interface FunctionalInterf { void m(); boolean equals(Object o); } 
  • это порождает ошибку:

     @FunctionalInterface public interface FunctionalInterf { void m(); boolean equals(); } 

    Множество неперехваченных абстрактных методов, найденных в интерфейсе FunctionalInterf

Документы Java говорят:

Обратите внимание, что всегда безопасно не переопределять Object.equals (Object). Однако переопределение этого метода может в некоторых случаях повысить производительность, позволяя программам определять, что два отдельных компаратора налагают один и тот же порядок.

Может быть, компаратор особенный? Может быть, хотя это интерфейс, есть некоторая реализация по умолчанию equals() которая вызывает compare() ? Алгоритмически это тривиально.

Я думал, что все методы, объявленные в интерфейсах, были абстрактными (т. Е. Без реализации по умолчанию). Но, может быть, я что-то упустил.

Определение:

Если интерфейс содержит только один абстрактный метод, то такой тип интерфейса называется функциональным интерфейсом.

Применение:

  1. Как только мы напишем выражение Lambda «->», чтобы вызвать его функциональность, в этом контексте нам нужен функциональный интерфейс.
  2. Мы можем использовать ссылку на функциональный интерфейс для ссылки на выражение Lambda.
  3. Внутри функционального интерфейса мы можем иметь один абстрактный метод и n число стандартных / статических методов.

Функциональный интерфейс в отношении наследования:

Если интерфейс расширяет функциональный интерфейс, а дочерний интерфейс не содержит абстрактного метода, тогда дочерний интерфейс также считается функциональным интерфейсом.

Функциональный интерфейс не является новым для java, который уже используется в следующих интерфейсах API:

  1. Runnable: содержит только метод run ().
  2. Callable: содержит только метод call ().
  3. Comparable: содержит метод compareTo ().