Na czym polega wykorzystanie interfejsu funkcjonalnego w Javie 8?
Natknąłem się na nowy termin o nazwie Functional Interface W Java 8.
Mogłem znaleźć tylko jedno zastosowanie tego interfejsu podczas pracy z wyrażeniami lambda .
Java 8 udostępnia wbudowane interfejsy funkcjonalne i jeśli chcemy zdefiniować dowolny interfejs funkcjonalny, możemy użyć adnotacji @FunctionalInterface
. Pozwoli nam zadeklarować tylko jedną metodę w interfejsie.
Na przykład:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
Jak przydatny jest w Javie 8 inny niż tylko praca z wyrażeniami lambda ?
Pytanie tutaj jest inne od tego, które zadałem. Pytanie, po co nam funkcjonalny interfejs podczas pracy z wyrażeniem Lambda. Moje pytanie brzmi: po co używać funkcjonalnego interfejsuinnego niż bezpośrednio z wyrażeniami lambda?
10 answers
@FunctionalInterface
adnotacja jest przydatna do sprawdzania czasu kompilacji kodu. Nie możesz mieć więcej niż jednej metody poza static
, default
i abstrakcyjne metody, które nadpisują metody w {[6] } w twoim @FunctionalInterface
lub dowolnym innym interfejsie używanym jako interfejs funkcjonalny.
Ale możesz używać lambda bez tej adnotacji, jak również możesz nadpisać metody bez @Override
adnotacji.
From docs
Interfejs funkcjonalny ma dokładnie jedną abstrakcyjną metodę. Od default metody mają implementację, nie są abstrakcyjne. Jeśli interfejs deklaruje metodę abstrakcyjną nadrzędną wobec jednej z publicznych metod java.lang.Obiekt, który również nie liczy się do interfejsu metody abstrakcyjne liczą się, ponieważ każda implementacja interfejsu będzie mieć implementację z Javy.lang.Obiekt lub gdzie indziej
To może być użyte w wyrażeniu lambda:
public interface Foo {
public void doSomething();
}
To Nie może być użyte w lambdzie wyrażenie:
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Ale To da błąd kompilacji :
@FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Nieprawidłowa adnotacja '@ FunctionalInterface'; Foo nie jest funkcją interfejs
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-03 04:20:29
Funkcjonalne interfejsy mają jedną funkcjonalność do wykazania. Na przykład do celów porównania używany jest porównywalny interfejs z pojedynczą metodą "compareTo". W Javie 8 zdefiniowano wiele funkcjonalnych interfejsów , które mają być szeroko stosowane w wyrażeniach lambda .
Wprowadzono adnotację - @FunctionalInterface
, która może być używana do błędów na poziomie kompilatora, gdy interfejs, który dodałeś, nie jest poprawnym interfejsem funkcjonalnym.
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
Spróbujmy dodać Inna abstrakcyjna metoda:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
int operationMultiply(int a, int b);
}
Powyżej spowoduje błąd kompilatora, jak podano poniżej:
Unexpected @FunctionalInterface annotation
@FunctionalInterface ^ MathOperation is not a functional interface
multiple non-overriding abstract methods found in interface MathOperation
Interfejs funkcjonalny jest poprawny, nawet jeśli adnotacja @FunctionalInterface
zostałaby pominięta. Służy tylko do informowania kompilatora o wymuszeniu pojedynczej abstrakcyjnej metody wewnątrz interfejsu.
interface MathOperation {
int operation(int a, int b);
}
Koncepcyjnie interfejs funkcjonalny ma dokładnie jedną abstrakcyjną metodę. Ponieważ metody domyślne mają implementację, nie są abstrakcyjne. Ponieważ metody domyślne nie są abstrakcyjne, jesteś darmowe dodawanie domyślnych metod do funkcjonalnego interfejsu, ile chcesz.
Poniżej znajduje się poprawny interfejs funkcjonalny:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
default void doSomeMathOperation(){
//Method body
}
}
Jeśli interfejs deklaruje abstrakcyjną metodę nadpisującą jedną z publicznych metod Javy.lang.Obiekt, który również nie liczy do abstrakcyjnych metod interfejsu, ponieważ każda implementacja interfejsu będzie miała implementację z Javy.lang.Obiekt lub gdzie indziej.
Np. Poniżej znajduje się prawidłowa funkcjonalność interfejs, mimo że zadeklarował dwie abstrakcyjne metody. Dlaczego? Ponieważ jedna z tych abstrakcyjnych metod " equals ()", która ma sygnaturę równą publicznej metodzie w klasie obiektu.
@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
}
Podczas gdy zamierzone użycie interfejsów funkcjonalnych jest dla wyrażeń lambda, odniesienia do metod i odniesienia do konstruktorów , nadal mogą być używane, jak każdy interfejs, z anonimowymi klasami, zaimplementowanymi przez klasy lub utworzonymi przez metody fabryczne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 14:35:50
Dokumentacja rzeczywiście robi różnicę między celem
Typ adnotacji informacyjnej używany do wskazania, że deklaracja typu interfejsu ma być interfejsem funkcjonalnym zgodnie ze specyfikacją języka Java.
I przypadek użycia
Zauważ, że instancje interfejsów funkcjonalnych mogą być tworzone za pomocą wyrażeń lambda, odniesień do metod lub odniesień do konstruktorów.
Którego sformułowanie nie wyklucza innych przypadków użycia w ogóle. Ponieważ głównym celem jest wskazanie functional interface, Twoje pytanie sprowadza się do "Czy istnieją inne przypadki użyciafunctional interfaces INNE niż wyrażenia lambda i odniesienia do metod/konstruktorów?"
Ponieważ functional interface jest konstrukcją języka Java zdefiniowaną przez specyfikację języka Java, tylko ta specyfikacja może odpowiedzieć na to pytanie:
JLS §9.8. Interfejsy Funkcjonalne :
…
Oprócz zwykłego procesu tworzenia instancji interfejsu poprzez deklarowanie i tworzenie instancji klasy (§15.9), instancje interfejsów funkcjonalnych mogą być tworzone za pomocą wyrażeń referencyjnych metody i wyrażeń lambda (§15.13, §15.27).
Więc specyfikacja języka Java nie mówi inaczej, jedynym przypadkiem użycia wspomnianym w tej sekcji jest tworzenie instancji interfejsu z wyrażeniami referencyjnymi metod i wyrażenia lambda. (Obejmuje to odwołania do konstruktorów, ponieważ są one odnotowane jako jedna z form wyrażenia odniesienia do metody w specyfikacji).
Więc w jednym zdaniu, Nie, Nie ma innego przypadku użycia tego w Java 8.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 08:34:19
Wcale nie. Wyrażenia Lambda są jedynym punktem tej adnotacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 06:25:24
Wyrażenie lambda może być przypisane do typu functional interface, podobnie jak odwołania do metod i klasy anonimowe.
Jedną miłą rzeczą w specyficznych interfejsach funkcjonalnych w java.util.function
jest to, że mogą one być tworzone w celu tworzenia nowych funkcji (takich jak Function.andThen
i Function.compose
, Predicate.and
, itd.) ze względu na poręczne metody domyślne, które zawierają.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 06:46:44
Jak powiedzieli inni, interfejs funkcjonalny jest interfejsem, który eksponuje jedną metodę. Może mieć więcej niż jedną metodę, ale wszystkie inne muszą mieć domyślną implementację. Powodem, dla którego nazywa się go "funkcjonalnym interfejsem", jest to, że skutecznie działa jako funkcja. Ponieważ można przekazać interfejsy jako parametry, oznacza to, że funkcje są teraz "obywatelami pierwszej klasy", jak w funkcyjnych językach programowania. Ma to wiele zalet, a podczas korzystania ze strumienia zobaczysz je dość często API. Oczywiście, wyrażenia lambda są dla nich głównym oczywistym zastosowaniem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 14:39:56
Interfejs z tylko jedną abstrakcyjną metodą nazywa się interfejsem funkcjonalnym. Używanie @FunctionalInterface nie jest obowiązkowe, ale najlepiej jest używać go z funkcjonalnymi interfejsami, aby uniknąć przypadkowego dodawania dodatkowych metod. Jeśli interfejs jest adnotowany adnotacją @ FunctionalInterface i staramy się mieć więcej niż jedną abstrakcyjną metodę, powoduje to błąd kompilatora.
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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-03 09:47:49
@FunctionalInterface
czy nowa adnotacja została wydana w Javie 8 i zapewnia typy docelowe dla wyrażeń lambda i jest używana przy sprawdzaniu czasu kompilacji kodu.
Kiedy chcesz go użyć:
1-twój interfejs nie może mieć więcej niż jedną abstrakcyjną metodę, w przeciwnym razie zostanie podany błąd kompilacji.
1-twój interfejs powinien być czysty, co oznacza, że interfejs funkcjonalny ma być zaimplementowany przez klasy bezstanowe, exmple z pure is Comparator
interfejs ponieważ nie zależy od stanu implementatorów, w tym przypadku nie zostanie podany błąd kompilacji, ale w wielu przypadkach nie będzie można używać lambda z tego typu interfejsami
Pakiet java.util.function
zawiera różne interfejsy funkcjonalne ogólnego przeznaczenia, takie jak Predicate
, Consumer
, Function
, i Supplier
.
Należy również pamiętać, że można używać lambda bez tej adnotacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-17 17:50:41
Oprócz innych odpowiedzi, myślę, że główny powód "dlaczego używanie interfejsu funkcjonalnego innego niż bezpośrednio z wyrażeniami lambda" może być związany z naturą języka Java, który jest zorientowany obiektowo.
Główne atrybuty wyrażeń Lambda to: 1. Mogą być przekazywane około 2. i mogą być wykonane w przyszłości w określonym czasie (kilka razy). Teraz, aby wspierać tę funkcję w językach, niektóre inne języki zajmują się po prostu tą sprawą.
Na przykład w Java Script, a funkcja (funkcja anonimowa lub literały funkcji) może być zaadresowana jako obiekt. Tak więc, można je tworzyć w prosty sposób, a także można je przypisać do zmiennej i tak dalej. Na przykład:
var myFunction = function (...) {
...;
}
alert(myFunction(...));
Lub poprzez ES6, można użyć funkcji strzałki.
const myFunction = ... => ...
Do tej pory projektanci języka Java nie akceptowali obsługi wspomnianych funkcji w ten sposób (techniki programowania funkcyjnego). Uważają, że język Java jest zorientowany obiektowo i dlatego powinni rozwiązać ten problem poprzez Techniki zorientowane obiektowo. Nie chcą przegapić prostoty i spójności języka Java.
Dlatego używają interfejsów, ponieważ gdy potrzebny jest obiekt interfejsu z tylko jedną metodą (mam na myśli interfejs funkcjonalny), można go zastąpić wyrażeniem lambda. Np.:
ActionListener listener = event -> ...;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-14 13:44:00
Możesz używać lambda w Javie 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");
}
Aby uzyskać więcej informacji o Java Lambdas i FunctionalInterfaces
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-17 06:06:05