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

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

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

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

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

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

Но в интерфейсе Comparator методы compare и 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

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

    A.

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

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

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

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

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

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

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

    Применение:

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

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

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

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

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

    До Java 8 интерфейс мог объявлять только один или несколько методов, также известный как абстрактный метод (метод без реализации, только подпись). Начиная с Java 8, интерфейс может также реализовывать один или несколько методов (известный как метод интерфейса по умолчанию) и статические методы вместе с абстрактными методами. Методы интерфейса по умолчанию отмечены по умолчанию.

    Итак, вопрос в том, что такое функциональный интерфейс? Интерфейс с единым абстрактным методом (SAM) называется функциональным интерфейсом.

    Что значит –

    1. Интерфейс с единым абстрактным методом – это функциональный интерфейс
    2. Интерфейс с единым абстрактным методом и ноль или более методов по умолчанию и ноль или более статический метод также является допустимым функциональным интерфейсом.

    Более подробно с примером кода https://readtorakesh.blogspot.com/2018/08/functional-interface-java8.html

    Давайте будем гением компьютера.