Что такое функциональный интерфейс в Java 8?

Я наткнулся на новый термин " Функциональный интерфейс" на Java 8.

Я мог найти только одно использование этого интерфейса при работе с лямбда-выражениями.

Java 8 предоставляет некоторые встроенные функциональные интерфейсы, и если мы хотим определить любой функциональный интерфейс, мы можем использовать аннотацию @FunctionalInterface. Это позволит нам объявить только один метод в интерфейсе.

Например:

@FunctionalInterface
interface MathOperation {
    int operation(int a, int b);
}

Насколько полезно в Java 8, кроме как работать с лямбда-выражениями?

Вопрос здесь отличается от того, который я задал. Он спрашивает, зачем нужен функциональный интерфейс при работе с выражением Lambda. Мой вопрос: зачем использовать функциональный интерфейс иначе, чем непосредственно с лямбда-выражениями?

Ответ 1

@FunctionalInterface аннотация полезна для проверки времени компиляции вашего кода. У вас не может быть более одного метода помимо static, default и абстрактных методов, которые переопределяют методы в Object в вашем @FunctionalInterface или любом другом интерфейсе, используемом в качестве функционального интерфейса.

Но вы можете использовать lambdas без этой аннотации, а также вы можете переопределять методы без аннотации @Override.

Из документов

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

Этот можно использовать в выражении лямбда:

public interface Foo {
  public void doSomething();
}

Этот нельзя использовать в выражении лямбда:

public interface Foo {
  public void doSomething();
  public void doSomethingElse();
}

Но это даст ошибку компиляции:

@FunctionalInterface
public interface Foo {
  public void doSomething();
  public void doSomethingElse();
}

Недействительная аннотация @FunctionalInterface; Foo не является функциональным Интерфейс

Ответ 2

Функциональные интерфейсы имеют одну функциональность для показа. Например, для сравнения используется интерфейс Comparable с единственным методом 'compareTo. Java 8 определила множество функциональных интерфейсов , которые будут широко использоваться в лямбда-выражениях.

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

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
 }

Попробуем добавить еще один абстрактный метод:

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
      int operationMultiply(int a, int b);
 }

Выше приведена ошибка компилятора, приведенная ниже:

Unexpected @FunctionalInterface annotation
@FunctionalInterface ^ MathOperation is not a functional interface
multiple non-overriding abstract methods found in interface MathOperation

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

 interface MathOperation {
      int operation(int a, int b);
 }

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

Ниже приведен действительный функциональный интерфейс:

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
      default void doSomeMathOperation(){
       //Method body
      }
 }

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

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

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
      @Override
      public String toString();  //Overridden from Object class
      @Override
      public boolean equals(Object obj); //Overridden from Object class
 }

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

Ответ 3

Совсем нет. Лямбда-выражения - это единственная точка этой аннотации.

Ответ 4

Документация действительно отличает цель

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

и прецедент

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

формулировка которой не исключает других случаев использования в целом. Поскольку основной целью является указание функционального интерфейса, ваш фактический вопрос сводится к "Есть ли другие варианты использования для функциональных интерфейсов, отличных от лямбда-выражений и ссылок на метод/конструктор?"

Поскольку функциональный интерфейс представляет собой конструкцию языка Java, определенную спецификацией языка Java, только эта спецификация может ответить на этот вопрос:

JLS §9.8. Функциональные интерфейсы:

...

В дополнение к обычному процессу создания экземпляра интерфейса путем объявления и создания экземпляра класса (§15.9) экземпляры функциональных интерфейсов могут быть созданы с помощью ссылочных выражений метода и лямбда-выражений (§15.13, §15.27).

Таким образом, спецификация языка Java не говорит иначе, единственным вариантом использования, упомянутым в этом разделе, является создание экземпляров интерфейса с помощью ссылочных выражений метода и лямбда-выражений. (Это включает ссылки на конструкторы, поскольку они отмечены как одна из форм ссылочного выражения метода в спецификации).

Итак, в одном предложении нет, в Java 8 нет другого варианта использования.

Ответ 5

Как говорили другие, функциональный интерфейс представляет собой интерфейс, который предоставляет один метод. Он может иметь несколько методов, но все остальные должны иметь реализацию по умолчанию. Причина, по которой он называется "функциональный интерфейс", заключается в том, что он эффективно действует как функция. Поскольку вы можете передавать интерфейсы в качестве параметров, это означает, что функции теперь являются "первоклассными гражданами", как в языках функционального программирования. Это имеет много преимуществ, и вы увидите их довольно много при использовании Stream API. Конечно, лямбда-выражения являются для них главным очевидным.

Ответ 6

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

Одна хорошая вещь о конкретных функциональных интерфейсах в java.util.function заключается в том, что они могут быть созданы для создания новых функций (например, Function.andThen и Function.compose, Predicate.and и т.д.) из-за удобных методов по умолчанию, которые они содержат.

Ответ 7

Интерфейс только с одним абстрактным методом называется функциональным интерфейсом. Не обязательно использовать @FunctionalInterface, но лучше всего использовать его с функциональными интерфейсами, чтобы избежать случайного добавления дополнительных методов. Если интерфейс аннотируется аннотацией @FunctionalInterface, и мы пытаемся иметь более одного абстрактного метода, он выдает ошибку компилятора.

package com.akhi;
    @FunctionalInterface
    public interface FucnctionalDemo {

      void letsDoSomething();
      //void letsGo();      //invalid because another abstract method does not allow
      public String toString();    // valid because toString from Object 
      public boolean equals(Object o); //valid

      public static int sum(int a,int b)   // valid because method static
        {   
            return a+b;
        }
        public default int sub(int a,int b)   //valid because method default
        {
            return a-b;
        }
    }

Ответ 8

@FunctionalInterface - это новая аннотация, выпущенная с помощью Java 8 и предоставляющая типы целей для лямбда-выражений, и она используется для проверки времени компиляции вашего кода.

Когда вы хотите использовать его:

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

1- Ваш интерфейс должен быть чистым, что означает, что функциональный интерфейс предназначен для осуществляться лицами без классов, exmple чистого является Comparator интерфейса, потому что его не зависит от состояния реализаторов в этом случае не будет дано Нет ошибка компиляции, но во многом случаев вы не сможете использовать лямбда с такими интерфейсами

Пакет java.util.function содержит различные функциональные интерфейсы общего назначения, такие как Predicate, Consumer, Function и Supplier.

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

Ответ 9

Вы можете использовать лямбду в Java 8

public static void main(String[] args) {
    tentimes(inputPrm - > System.out.println(inputPrm));
    //tentimes(System.out::println);  // You can also replace lambda with static method reference
}

public static void tentimes(Consumer myFunction) {
    for (int i = 0; i < 10; i++)
        myFunction.accept("hello");
}

Для получения дополнительной информации о Java Lambdas и FunctionalInterfaces

Ответ 10

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

Основными атрибутами лямбда-выражений являются: 1. Их можно передавать около 2. и они могут выполняться в будущем в определенное время (несколько раз). Теперь, чтобы поддержать эту функцию на языках, некоторые другие языки имеют дело только с этим вопросом.

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

var myFunction = function (...) {
    ...;
}
alert(myFunction(...));

или через ES6, вы можете использовать функцию стрелки.

const myFunction = ... => ...

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

Поэтому они используют интерфейсы, так как когда объект интерфейса только с одним методом (я имею в виду функциональный интерфейс), вы можете заменить его на лямбда-выражение. Такие как:

ActionListener listener = event -> ...;

Ответ 11

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

  • Введено в Java 8
  • Интерфейс, который содержит "единственный абстрактный" метод.

Пример 1:

   interface CalcArea {   // --functional interface
        double calcArea(double rad);
    }           

Пример 2:

interface CalcGeometry { // --functional interface
    double calcArea(double rad);
    default double calcPeri(double rad) {
        return 0.0;
    }
}       

Пример 3:

interface CalcGeometry {  // -- not functional interface
    double calcArea(double rad);
    double calcPeri(double rad);
}   

Аннотация Java8 - @FunctionalInterface

  • Проверка аннотации, что интерфейс содержит только один абстрактный метод. Если нет, поднять ошибку.
  • Даже если @FunctionalInterface отсутствует, он все же является функциональным интерфейсом (если используется один абстрактный метод). Аннотация помогает избежать ошибок.
  • Функциональный интерфейс может иметь дополнительные статические и стандартные методы.
  • например, Iterable <>, Comparable <>, Comparator <>.

Приложения функционального интерфейса:

  • Ссылки на метод
  • Лямбда-выражение
  • Ссылки на конструктор

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

Ответ 12

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