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


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

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

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

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

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

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

6 60

6 ответов:

с та же страница, которую вы связали с:

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

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

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

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

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

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

например:

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

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

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

    несколько не переопределяющих абстрактных методов, найденных в интерфейсе FunctionalInterf

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

А.

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

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

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

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

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

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

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

использование:

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

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

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

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

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

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

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

Что означает -

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

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